00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
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
00312 updatePermPixmaps();
00313 }
00314
00315 void KACLListViewItem::calcEffectiveRights()
00316 {
00317 QString strEffective = QString( "---" );
00318
00319
00320
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
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 }
00347 else
00348 {
00349
00350 strEffective[0] = ( value & ACL_READ ) ? 'r' : '-';
00351 strEffective[1] = ( value & ACL_WRITE ) ? 'w' : '-';
00352 strEffective[2] = ( value & ACL_EXECUTE ) ? 'x' : '-';
00353
00354
00355
00356
00357
00358
00359
00360
00361
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;
00393 if ( type == KACLListView::Mask && !isDefault ) {
00394 m_pACLListView->setMaskPermissions( value );
00395 }
00396 calcEffectiveRights();
00397 updatePermPixmaps();
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
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
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
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
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
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
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
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
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
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
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
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 ;
00884 }
00885 }
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
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
00939 return 0;
00940 }
00941
00942
00943 void KACLListView::setMaskPartialPermissions( acl_perm_t )
00944 {
00945
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
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;
01003 if ( item->type == Mask && !item->isDefault ) {
01004 m_hasMask = true;
01005 m_mask = item->value;
01006 }
01007 if ( item->isDefault && !hasDefaultEntries() ) {
01008
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
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
01041
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
01085
01086
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
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