• Skip to content
  • Skip to link menu
KDE 4.1 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 
00642     // Load the avatars
00643     for ( int i=0; i < LAST_IDX; ++i ) {
00644         s_itemAttributes[i].pixmap = new QPixmap( QString::fromLatin1(":/images/%1").arg(s_itemAttributes[i].pixmapName) );
00645     }
00646     m_yesPixmap = new QPixmap( ":/images/yes.png" );
00647     m_yesPartialPixmap = new QPixmap( ":/images/yespartial.png" );
00648 
00649 
00650     // fill the lists of all legal users and groups
00651     struct passwd *user = 0;
00652     setpwent();
00653     while ( ( user = getpwent() ) != 0 ) {
00654        m_allUsers << QString::fromLatin1( user->pw_name );
00655     }
00656     endpwent();
00657 
00658     struct group *gr = 0;
00659     setgrent();
00660     while ( ( gr = getgrent() ) != 0 ) {
00661        m_allGroups << QString::fromLatin1( gr->gr_name );
00662     }
00663     endgrent();
00664     m_allUsers.sort();
00665     m_allGroups.sort();
00666 
00667     connect( this, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ),
00668              this, SLOT( slotItemClicked( QTreeWidgetItem*, int ) ) );
00669 }
00670 
00671 
00672 KACLListView::~KACLListView()
00673 {
00674     for ( int i=0; i < LAST_IDX; ++i ) {
00675        delete s_itemAttributes[i].pixmap;
00676     }
00677     delete m_yesPixmap;
00678     delete m_yesPartialPixmap;
00679 }
00680 
00681 QStringList KACLListView::allowedUsers( bool defaults, KACLListViewItem *allowedItem )
00682 {
00683     QStringList allowedUsers = m_allUsers;
00684     QTreeWidgetItemIterator it( this );
00685     while ( *it ) {
00686         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00687         ++it;
00688         if ( !item->type == NamedUser || item->isDefault != defaults ) continue;
00689         if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00690         allowedUsers.removeAll( item->qualifier );
00691     }
00692     return allowedUsers;
00693 }
00694 
00695 QStringList KACLListView::allowedGroups( bool defaults, KACLListViewItem *allowedItem )
00696 {
00697     QStringList allowedGroups = m_allGroups;
00698     QTreeWidgetItemIterator it( this );
00699     while ( *it ) {
00700         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00701         ++it;
00702         if ( !item->type == NamedGroup || item->isDefault != defaults ) continue;
00703         if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00704         allowedGroups.removeAll( item->qualifier );
00705     }
00706     return allowedGroups;
00707 }
00708 
00709 void KACLListView::fillItemsFromACL( const KACL &pACL, bool defaults )
00710 {
00711     // clear out old entries of that ilk
00712     QTreeWidgetItemIterator it( this );
00713     while ( KACLListViewItem *item = static_cast<KACLListViewItem*>( *it ) ) {
00714         ++it;
00715         if ( item->isDefault == defaults )
00716             delete item;
00717     }
00718     KACLListViewItem *item =
00719         new KACLListViewItem( this, User, pACL.ownerPermissions(), defaults );
00720 
00721     item = new KACLListViewItem( this, Group, pACL.owningGroupPermissions(), defaults );
00722 
00723     item = new KACLListViewItem( this, Others, pACL.othersPermissions(), defaults );
00724 
00725     bool hasMask = false;
00726     unsigned short mask = pACL.maskPermissions( hasMask );
00727     if ( hasMask ) {
00728         item = new KACLListViewItem( this, Mask, mask, defaults );
00729     }
00730 
00731     // read all named user entries
00732     const ACLUserPermissionsList &userList =  pACL.allUserPermissions();
00733     ACLUserPermissionsConstIterator itu = userList.begin();
00734     while ( itu != userList.end() ) {
00735         new KACLListViewItem( this, NamedUser, (*itu).second, defaults, (*itu).first );
00736         ++itu;
00737     }
00738 
00739     // and now all named groups
00740     const ACLUserPermissionsList &groupList =  pACL.allGroupPermissions();
00741     ACLUserPermissionsConstIterator itg = groupList.begin();
00742     while ( itg != groupList.end() ) {
00743         new KACLListViewItem( this, NamedGroup, (*itg).second, defaults, (*itg).first );
00744         ++itg;
00745     }
00746 }
00747 
00748 void KACLListView::setACL( const KACL &acl )
00749 {
00750     if ( !acl.isValid() ) return;
00751     // Remove any entries left over from displaying a previous ACL
00752     m_ACL = acl;
00753     fillItemsFromACL( m_ACL );
00754 
00755     m_mask = acl.maskPermissions( m_hasMask );
00756     calculateEffectiveRights();
00757 }
00758 
00759 void KACLListView::setDefaultACL( const KACL &acl )
00760 {
00761     if ( !acl.isValid() ) return;
00762     m_defaultACL = acl;
00763     fillItemsFromACL( m_defaultACL, true );
00764     calculateEffectiveRights();
00765 }
00766 
00767 KACL KACLListView::itemsToACL( bool defaults ) const
00768 {
00769     KACL newACL( 0 );
00770     bool atLeastOneEntry = false;
00771     ACLUserPermissionsList users;
00772     ACLGroupPermissionsList groups;
00773     QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00774     while ( QTreeWidgetItem* qlvi = *it ) {
00775         ++it;
00776         const KACLListViewItem* item = static_cast<KACLListViewItem*>( qlvi );
00777         if ( item->isDefault != defaults ) continue;
00778         atLeastOneEntry = true;
00779         switch ( item->type ) {
00780             case User:
00781                 newACL.setOwnerPermissions( item->value );
00782                 break;
00783             case Group:
00784                 newACL.setOwningGroupPermissions( item->value );
00785                 break;
00786             case Others:
00787                 newACL.setOthersPermissions( item->value );
00788                 break;
00789             case Mask:
00790                 newACL.setMaskPermissions( item->value );
00791                 break;
00792             case NamedUser:
00793                 users.append( qMakePair( item->text( 1 ), item->value ) );
00794                 break;
00795             case NamedGroup:
00796                 groups.append( qMakePair( item->text( 1 ), item->value ) );
00797                 break;
00798             default:
00799                 break;
00800         }
00801     }
00802     if ( atLeastOneEntry ) {
00803         newACL.setAllUserPermissions( users );
00804         newACL.setAllGroupPermissions( groups );
00805         if ( newACL.isValid() )
00806             return newACL;
00807     }
00808     return KACL();
00809 }
00810 
00811 KACL KACLListView::getACL()
00812 {
00813     return itemsToACL( false );
00814 }
00815 
00816 
00817 KACL KACLListView::getDefaultACL()
00818 {
00819     return itemsToACL( true );
00820 }
00821 
00822 void KACLListView::contentsMousePressEvent( QMouseEvent * e )
00823 {
00824     /*
00825     QTreeWidgetItem *clickedItem = itemAt( e->pos() );
00826     if ( !clickedItem ) return;
00827     // if the click is on an as yet unselected item, select it first
00828     if ( !clickedItem->isSelected() )
00829         QAbstractItemView::contentsMousePressEvent( e );
00830 
00831     if ( !currentItem() ) return;
00832     int column = header()->sectionAt( e->x() );
00833     acl_perm_t perm;
00834     switch ( column )
00835     {
00836         case 2:
00837             perm = ACL_READ;
00838             break;
00839         case 3:
00840             perm = ACL_WRITE;
00841             break;
00842         case 4:
00843             perm = ACL_EXECUTE;
00844             break;
00845         default:
00846             return QTreeWidget::contentsMousePressEvent( e );
00847     }
00848     KACLListViewItem* referenceItem = static_cast<KACLListViewItem*>( clickedItem );
00849     unsigned short referenceHadItSet = referenceItem->value & perm;
00850     QTreeWidgetItemIterator it( this );
00851     while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( *it ) ) {
00852         ++it;
00853         if ( !item->isSelected() ) continue;
00854         // toggle those with the same value as the clicked item, leave the others
00855         if ( referenceHadItSet == ( item->value & perm ) )
00856             item->togglePerm( perm );
00857     }
00858      */
00859 }
00860 
00861 void KACLListView::slotItemClicked( QTreeWidgetItem* pItem,  int col )
00862 {
00863     if ( !pItem ) return;
00864 
00865     QTreeWidgetItemIterator it( this );
00866     while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( *it ) ) {
00867         ++it;
00868         if ( !item->isSelected() ) continue;
00869         switch ( col )
00870         {
00871             case 2:
00872                 item->togglePerm( ACL_READ );
00873                 break;
00874             case 3:
00875                 item->togglePerm( ACL_WRITE );
00876                 break;
00877             case 4:
00878                 item->togglePerm( ACL_EXECUTE );
00879                 break;
00880 
00881             default:
00882                 ; // Do nothing
00883         }
00884     }
00885     /*
00886     // Has the user changed one of the required entries in a default ACL?
00887     if ( m_pACL->aclType() == ACL_TYPE_DEFAULT &&
00888     ( col == 2 || col == 3 || col == 4 ) &&
00889     ( pACLItem->entryType() == ACL_USER_OBJ ||
00890     pACLItem->entryType() == ACL_GROUP_OBJ ||
00891     pACLItem->entryType() == ACL_OTHER ) )
00892     {
00893     // Mark the required entries as no longer being partial entries.
00894     // That is, they will get applied to all selected directories.
00895     KACLListViewItem* pUserObj = findACLEntryByType( this, ACL_USER_OBJ );
00896     pUserObj->entry()->setPartialEntry( false );
00897 
00898     KACLListViewItem* pGroupObj = findACLEntryByType( this, ACL_GROUP_OBJ );
00899     pGroupObj->entry()->setPartialEntry( false );
00900 
00901     KACLListViewItem* pOther = findACLEntryByType( this, ACL_OTHER );
00902     pOther->entry()->setPartialEntry( false );
00903 
00904     update();
00905     }
00906      */
00907 }
00908 
00909 
00910 void KACLListView::calculateEffectiveRights()
00911 {
00912     QTreeWidgetItemIterator it( this );
00913     KACLListViewItem* pItem;
00914     while ( ( pItem = dynamic_cast<KACLListViewItem*>( *it ) ) != 0 )
00915     {
00916         ++it;
00917         pItem->calcEffectiveRights();
00918     }
00919 }
00920 
00921 
00922 unsigned short KACLListView::maskPermissions() const
00923 {
00924   return m_mask;
00925 }
00926 
00927 
00928 void KACLListView::setMaskPermissions( unsigned short maskPerms )
00929 {
00930     m_mask = maskPerms;
00931     calculateEffectiveRights();
00932 }
00933 
00934 
00935 acl_perm_t KACLListView::maskPartialPermissions() const
00936 {
00937   //  return m_pMaskEntry->m_partialPerms;
00938   return 0;
00939 }
00940 
00941 
00942 void KACLListView::setMaskPartialPermissions( acl_perm_t /*maskPartialPerms*/ )
00943 {
00944     //m_pMaskEntry->m_partialPerms = maskPartialPerms;
00945     calculateEffectiveRights();
00946 }
00947 
00948 bool KACLListView::hasDefaultEntries() const
00949 {
00950     QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00951     while ( *it ) {
00952         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00953         ++it;
00954         if ( item->isDefault ) return true;
00955     }
00956     return false;
00957 }
00958 
00959 const KACLListViewItem* KACLListView::findDefaultItemByType( EntryType type ) const
00960 {
00961     return findItemByType( type, true );
00962 }
00963 
00964 const KACLListViewItem* KACLListView::findItemByType( EntryType type, bool defaults ) const
00965 {
00966     QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00967     while ( *it ) {
00968         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00969         ++it;
00970         if ( item->isDefault == defaults && item->type == type ) {
00971             return item;
00972         }
00973     }
00974     return 0;
00975 }
00976 
00977 
00978 unsigned short KACLListView::calculateMaskValue( bool defaults ) const
00979 {
00980     // KACL auto-adds the relevant maks entries, so we can simply query
00981     bool dummy;
00982     return itemsToACL( defaults ).maskPermissions( dummy );
00983 }
00984 
00985 void KACLListView::slotAddEntry()
00986 {
00987     int allowedTypes = NamedUser | NamedGroup;
00988     if ( !m_hasMask )
00989         allowedTypes |= Mask;
00990     int allowedDefaultTypes = NamedUser | NamedGroup;
00991     if ( !findDefaultItemByType( Mask ) )
00992         allowedDefaultTypes |=  Mask;
00993     if ( !hasDefaultEntries() )
00994         allowedDefaultTypes |= User | Group;
00995     EditACLEntryDialog dlg( this, 0,
00996                             allowedUsers( false ), allowedGroups( false ),
00997                             allowedUsers( true ), allowedGroups( true ),
00998                             allowedTypes, allowedDefaultTypes, m_allowDefaults );
00999     dlg.exec();
01000     KACLListViewItem *item = dlg.item();
01001     if ( !item ) return; // canceled
01002     if ( item->type == Mask && !item->isDefault ) {
01003         m_hasMask = true;
01004         m_mask = item->value;
01005     }
01006     if ( item->isDefault && !hasDefaultEntries() ) {
01007         // first default entry, fill in what is needed
01008         if ( item->type != User ) {
01009             unsigned short v = findDefaultItemByType( User )->value;
01010             new KACLListViewItem( this, User, v, true );
01011         }
01012         if ( item->type != Group ) {
01013             unsigned short v = findDefaultItemByType( Group )->value;
01014             new KACLListViewItem( this, Group, v, true );
01015         }
01016         if ( item->type != Others ) {
01017             unsigned short v = findDefaultItemByType( Others )->value;
01018             new KACLListViewItem( this, Others, v, true );
01019         }
01020     }
01021     const KACLListViewItem *defaultMaskItem = findDefaultItemByType( Mask );
01022     if ( item->isDefault && !defaultMaskItem ) {
01023         unsigned short v = calculateMaskValue( true );
01024         new KACLListViewItem( this, Mask, v, true );
01025     }
01026     if ( !item->isDefault && !m_hasMask &&
01027             ( item->type == Group
01028               || item->type == NamedUser
01029               || item->type == NamedGroup ) ) {
01030         // auto-add a mask entry
01031         unsigned short v = calculateMaskValue( false );
01032         new KACLListViewItem( this, Mask, v, false );
01033         m_hasMask = true;
01034         m_mask = v;
01035     }
01036     calculateEffectiveRights();
01037     sortItems( sortColumn(), Qt::AscendingOrder );
01038     setCurrentItem( item );
01039     // QTreeWidget doesn't seem to emit, in this case, and we need to update
01040     // the buttons...
01041     if ( topLevelItemCount() == 1 )
01042         emit currentItemChanged( item, item );
01043 }
01044 
01045 void KACLListView::slotEditEntry()
01046 {
01047     QTreeWidgetItem * current = currentItem();
01048     if ( !current ) return;
01049     KACLListViewItem *item = static_cast<KACLListViewItem*>( current );
01050     int allowedTypes = item->type | NamedUser | NamedGroup;
01051     bool itemWasMask = item->type == Mask;
01052     if ( !m_hasMask || itemWasMask )
01053         allowedTypes |= Mask;
01054     int allowedDefaultTypes = item->type | NamedUser | NamedGroup;
01055     if ( !findDefaultItemByType( Mask ) )
01056         allowedDefaultTypes |=  Mask;
01057     if ( !hasDefaultEntries() )
01058         allowedDefaultTypes |= User | Group;
01059 
01060     EditACLEntryDialog dlg( this, item,
01061                             allowedUsers( false, item ), allowedGroups( false, item ),
01062                             allowedUsers( true, item ), allowedGroups( true, item ),
01063                             allowedTypes, allowedDefaultTypes, m_allowDefaults );
01064     dlg.exec();
01065     if ( itemWasMask && item->type != Mask ) {
01066         m_hasMask = false;
01067         m_mask = 0;
01068     }
01069     if ( !itemWasMask && item->type == Mask ) {
01070         m_mask = item->value;
01071         m_hasMask = true;
01072     }
01073     calculateEffectiveRights();
01074     sortItems( sortColumn(), Qt::AscendingOrder );
01075 }
01076 
01077 void KACLListView::slotRemoveEntry()
01078 {
01079     QTreeWidgetItemIterator it( this, QTreeWidgetItemIterator::Selected );
01080     while ( *it ) {
01081         KACLListViewItem *item = static_cast<KACLListViewItem*>( *it );
01082         ++it;
01083         /* First check if it's a mask entry and if so, make sure that there is
01084          * either no name user or group entry, which means the mask can be
01085          * removed, or don't remove it, but reset it. That is allowed. */
01086         if ( item->type == Mask ) {
01087             bool itemWasDefault = item->isDefault;
01088             if ( !itemWasDefault && maskCanBeDeleted() ) {
01089                 m_hasMask= false;
01090                 m_mask = 0;
01091                 delete item;
01092             } else if ( itemWasDefault && defaultMaskCanBeDeleted() ) {
01093                 delete item;
01094             } else {
01095                 item->value = 0;
01096                 item->repaint();
01097             }
01098             if ( !itemWasDefault )
01099                 calculateEffectiveRights();
01100         } else {
01101             // for the base permissions, disable them, which is what libacl does
01102             if ( !item->isDefault &&
01103                     ( item->type == User
01104                       || item->type == Group
01105                       || item->type == Others ) ) {
01106                 item->value = 0;
01107                 item->repaint();
01108             } else {
01109                 delete item;
01110             }
01111         }
01112     }
01113 }
01114 
01115 bool KACLListView::maskCanBeDeleted() const
01116 {
01117    return !findItemByType( NamedUser ) && !findItemByType( NamedGroup );
01118 }
01119 
01120 bool KACLListView::defaultMaskCanBeDeleted() const
01121 {
01122     return !findDefaultItemByType( NamedUser ) && !findDefaultItemByType( NamedGroup );
01123 }
01124 
01125 #include "kacleditwidget.moc"
01126 #include "kacleditwidget_p.moc"
01127 #endif
01128 // 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
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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