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