49 #include <config-acl.h>
55 #include <sys/types.h>
62 #include <QtCore/QFile>
63 #include <QtCore/QDir>
64 #include <QtGui/QLabel>
65 #include <QtGui/QPushButton>
66 #include <QtGui/QCheckBox>
67 #include <QtCore/QMutableStringListIterator>
68 #include <QtCore/QTextIStream>
69 #include <QtGui/QPainter>
70 #include <QtGui/QLayout>
71 #include <QtGui/QStyle>
72 #include <QtGui/QProgressBar>
78 # include <sys/xattr.h>
129 #include "ui_kpropertiesdesktopbase.h"
130 #include "ui_kpropertiesdesktopadvbase.h"
131 #ifdef HAVE_POSIX_ACL
141 # warning TODO: port completely to win32
145 using namespace KDEPrivate;
149 if ( nameStr.endsWith(QLatin1String(
".desktop")) )
150 nameStr.truncate( nameStr.length() - 8 );
151 if ( nameStr.endsWith(QLatin1String(
".kdelnk")) )
152 nameStr.truncate( nameStr.length() - 7 );
158 mode_t KFilePermissionsPropsPlugin::fperm[3][4] = {
159 {S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID},
160 {S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID},
161 {S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX}
164 class KPropertiesDialog::KPropertiesDialogPrivate
173 ~KPropertiesDialogPrivate()
205 QList<KPropertiesDialogPlugin*> m_pageList;
210 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
214 Q_ASSERT( !item.
isNull() );
215 d->m_items.append(item);
217 d->m_singleUrl = item.
url();
218 Q_ASSERT(!d->m_singleUrl.isEmpty());
225 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
234 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
236 if ( _items.count() > 1 )
237 setCaption(
i18np(
"Properties for 1 item",
"Properties for %1 Selected Items", _items.count() ) );
241 Q_ASSERT( !_items.isEmpty() );
242 d->m_singleUrl = _items.first().url();
243 Q_ASSERT(!d->m_singleUrl.isEmpty());
252 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
256 d->m_singleUrl = _url;
261 d->m_items.append(
KFileItem(entry, _url));
268 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
272 d->m_singleUrl = _tempUrl;
273 d->m_defaultName = _defaultName;
274 d->m_currentDir = _currentDir;
275 Q_ASSERT(!d->m_singleUrl.isEmpty());
289 if (!localPath.isEmpty())
322 if (_items.count()==1) {
339 void KPropertiesDialog::KPropertiesDialogPrivate::init()
345 connect(q, SIGNAL(okClicked()), q, SLOT(slotOk()));
346 connect(q, SIGNAL(cancelClicked()), q, SLOT(slotCancel()));
351 q->restoreDialogSize(group);
356 if (d->fileSharePage) {
363 d->fileSharePage = page;
380 qDeleteAll(d->m_pageList);
389 connect (plugin, SIGNAL (changed()),
390 plugin, SLOT (setDirty()));
392 d->m_pageList.append(plugin);
397 return d->m_singleUrl;
402 return d->m_items.first();
412 return d->m_currentDir;
417 return d->m_defaultName;
423 return KFilePropsPlugin::supports( _items ) ||
424 KFilePermissionsPropsPlugin::supports( _items ) ||
425 KDesktopPropsPlugin::supports( _items ) ||
426 KUrlPropsPlugin::supports( _items ) ||
427 KDevicePropsPlugin::supports( _items ) ||
434 QList<KPropertiesDialogPlugin*>::const_iterator pageListIt;
435 d->m_aborted =
false;
442 for (pageListIt = d->m_pageList.constBegin(); pageListIt != d->m_pageList.constEnd(); ++pageListIt) {
443 if ( (*pageListIt)->isDirty() && filePropsPlugin )
454 for (pageListIt = d->m_pageList.constBegin(); pageListIt != d->m_pageList.constEnd() && !d->m_aborted; ++pageListIt) {
455 if ( (*pageListIt)->isDirty() )
457 kDebug( 250 ) <<
"applying changes for " << (*pageListIt)->metaObject()->className();
458 (*pageListIt)->applyChanges();
462 kDebug( 250 ) <<
"skipping page " << (*pageListIt)->metaObject()->className();
466 if ( !d->m_aborted && filePropsPlugin )
487 void KPropertiesDialog::KPropertiesDialogPrivate::insertPages()
489 if (m_items.isEmpty())
492 if ( KFilePropsPlugin::supports( m_items ) ) {
497 if ( KFilePermissionsPropsPlugin::supports( m_items ) ) {
502 if ( KDesktopPropsPlugin::supports( m_items ) ) {
507 if ( KUrlPropsPlugin::supports( m_items ) ) {
512 if ( KDevicePropsPlugin::supports( m_items ) ) {
529 if ( m_items.count() != 1 )
535 if ( mimetype.isEmpty() )
538 QString query = QString::fromLatin1(
539 "((not exist [X-KDE-Protocol]) or "
540 " ([X-KDE-Protocol] == '%1' ) )"
543 kDebug( 250 ) <<
"trader query: " << query;
549 plugin->setObjectName(ptr->
name());
551 q->insertPlugin(plugin);
557 Q_ASSERT(d->m_items.count() == 1);
558 kDebug(250) <<
"KPropertiesDialog::updateUrl (pre)" << _newUrl.
url();
559 KUrl newUrl = _newUrl;
560 emit
saveAs(d->m_singleUrl, newUrl);
561 kDebug(250) <<
"KPropertiesDialog::updateUrl (post)" << newUrl.
url();
563 d->m_singleUrl = newUrl;
564 d->m_items.first().setUrl(newUrl);
565 Q_ASSERT(!d->m_singleUrl.isEmpty());
569 if ( qobject_cast<KUrlPropsPlugin*>(it) ||
581 Q_ASSERT(d->m_items.count() == 1);
582 kDebug(250) <<
"KPropertiesDialog::rename " << _name;
585 if (!d->m_currentDir.isEmpty()) {
586 newUrl = d->m_currentDir;
589 QString tmpurl = d->m_singleUrl.url();
590 if (!tmpurl.isEmpty() && tmpurl.at(tmpurl.length() - 1) ==
'/') {
592 tmpurl.truncate(tmpurl.length() - 1);
606 class KPropertiesDialogPlugin::KPropertiesDialogPluginPrivate
609 KPropertiesDialogPluginPrivate()
612 ~KPropertiesDialogPluginPrivate()
621 :
QObject( _props ),d(new KPropertiesDialogPluginPrivate)
624 d->fontHeight = 2*
properties->fontMetrics().height();
633 #ifndef KDE_NO_DEPRECATED
657 kWarning(250) <<
"applyChanges() not implemented in page !";
662 return d->fontHeight;
667 class KFilePropsPlugin::KFilePropsPluginPrivate
670 KFilePropsPluginPrivate()
673 dirSizeUpdateTimer = 0L;
676 m_linkTargetLineEdit = 0;
678 ~KFilePropsPluginPrivate()
685 QTimer *dirSizeUpdateTimer;
705 bool m_bFromTemplate;
717 d->bIconChanged =
false;
719 kDebug(250) <<
"KFilePropsPlugin::KFilePropsPlugin bMultiple=" << d->bMultiple;
728 mode_t mode = item.
mode();
730 bool hasRoot = url.
path() == QLatin1String(
"/");
734 d->bKDesktopMode = protocol == QLatin1String(
"desktop") ||
743 magicMimeComment = magicMimeType->
comment();
746 if ( isReallyLocal ) {
747 directory = QDir::toNativeSeparators( directory.mid( 1 ) );
753 bool isTrash =
false;
754 d->m_bFromTemplate =
false;
757 uint iDirCount = hasDirs ? 1 : 0;
758 uint iFileCount = 1-iDirCount;
760 d->m_frame =
new QFrame();
763 QVBoxLayout *vbl =
new QVBoxLayout( d->m_frame );
765 vbl->setObjectName( QLatin1String(
"vbl" ) );
766 QGridLayout *grid =
new QGridLayout();
767 grid->setColumnStretch(0, 0);
768 grid->setColumnStretch(1, 0);
769 grid->setColumnStretch(2, 1);
771 vbl->addLayout(grid);
777 if ( !d->m_bFromTemplate ) {
789 if (d->bDesktopFile) {
790 determineRelativePath( path );
795 if ( filename.isEmpty() ) {
796 const QFileInfo finfo (item.
name());
797 filename = finfo.fileName();
799 d->m_bFromTemplate =
true;
802 d->oldFileName = filename;
807 if ( d->bKDesktopMode && d->bDesktopFile ) {
809 if (
config.desktopGroup().hasKey(
"Name" ) ) {
810 filename =
config.readName();
814 d->oldName = filename;
820 KFileItemList::const_iterator kit = items.begin();
821 const KFileItemList::const_iterator kend = items.end();
822 for ( ++kit ; kit != kend; ++kit )
825 kDebug(250) <<
"KFilePropsPlugin::KFilePropsPlugin " << url.
prettyUrl();
830 if ( bDesktopFile && (*kit).isDesktopFile() != bDesktopFile )
831 bDesktopFile =
false;
832 if ( (*kit).mode() != mode )
835 iconStr =
"document-multiple";
840 if ( !mimeComment.isNull() && (*kit).mimeComment() != mimeComment )
842 if ( isLocal && !magicMimeComment.isNull() ) {
844 if ( magicMimeType->
comment() != magicMimeComment )
845 magicMimeComment.clear();
848 if ( isLocal && url.
path() == QLatin1String(
"/") )
850 if ( (*kit).isDir() && !(*kit).isLink() )
858 totalSize += (*kit).size();
863 if (!isReallyLocal && !protocol.isEmpty())
867 directory += protocol;
871 if (!isTrash && (bDesktopFile || S_ISDIR(mode))
873 && enableIconButton())
876 int bsize = 66 + 2 * iconButton->style()->pixelMetric(QStyle::PM_ButtonMargin);
877 iconButton->setFixedSize(bsize, bsize);
881 if (bDesktopFile && isLocal) {
884 iconStr = group.readEntry(
"Icon" );
885 if (
config.hasDeviceType() )
893 d->iconArea = iconButton;
894 connect(iconButton, SIGNAL(iconChanged(
QString)),
895 this, SLOT(slotIconChanged()));
898 int bsize = 66 + 2 * iconLabel->style()->pixelMetric(QStyle::PM_ButtonMargin);
899 iconLabel->setFixedSize(bsize, bsize);
901 d->iconArea = iconLabel;
903 grid->addWidget(d->iconArea, curRow, 0, Qt::AlignLeft);
905 if (d->bMultiple || isTrash || hasRoot)
911 lab->setText( filename );
915 d->m_lined =
new KLineEdit( d->m_frame );
916 d->m_lined->setText(filename);
917 d->nameArea = d->m_lined;
918 d->m_lined->setFocus();
926 if ( !extension.isEmpty() )
927 d->m_lined->setSelection( 0, filename.length() - extension.length() - 1 );
930 int lastDot = filename.lastIndexOf(
'.');
932 d->m_lined->setSelection(0, lastDot);
935 connect( d->m_lined, SIGNAL(textChanged(
QString)),
936 this, SLOT(nameFileChanged(
QString)) );
939 grid->addWidget(d->nameArea, curRow++, 2);
942 grid->addWidget(sep, curRow, 0, 1, 3);
946 if (!mimeComment.isEmpty() && !isTrash) {
949 grid->addWidget(l, curRow, 0, Qt::AlignRight);
953 l =
new QLabel(mimeComment, box );
957 button->setIcon(
KIcon(QString::fromLatin1(
"configure")) );
958 const int pixmapSize = button->style()->pixelMetric(QStyle::PM_SmallIconSize);
959 button->setFixedSize( pixmapSize+8, pixmapSize+8 );
961 button->setToolTip(
i18n(
"Create new file type"));
963 button->setToolTip(
i18n(
"Edit file type"));
970 grid->addWidget(box, curRow++, 2);
973 if ( !magicMimeComment.isEmpty() && magicMimeComment != mimeComment )
975 l =
new QLabel(
i18n(
"Contents:"), d->m_frame );
976 grid->addWidget(l, curRow, 0, Qt::AlignRight);
978 l =
new QLabel(magicMimeComment, d->m_frame );
979 grid->addWidget(l, curRow++, 2);
982 if ( !directory.isEmpty() )
984 l =
new QLabel(
i18n(
"Location:"), d->m_frame );
985 grid->addWidget(l, curRow, 0, Qt::AlignRight);
989 l->setLayoutDirection(Qt::LeftToRight);
992 if (
properties->layoutDirection() == Qt::RightToLeft)
993 l->setAlignment( Qt::AlignRight );
994 l->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
995 grid->addWidget(l, curRow++, 2);
999 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1001 d->m_sizeLabel =
new QLabel( d->m_frame );
1002 grid->addWidget( d->m_sizeLabel, curRow++, 2 );
1006 d->m_sizeLabel->setText(QString::fromLatin1(
"%1 (%2)").arg(
KIO::convertSize(totalSize))
1008 d->m_sizeDetermineButton = 0L;
1009 d->m_sizeStopButton = 0L;
1013 QHBoxLayout * sizelay =
new QHBoxLayout();
1014 grid->addLayout( sizelay, curRow++, 2 );
1017 d->m_sizeDetermineButton =
new QPushButton(
i18n(
"Calculate"), d->m_frame );
1019 connect( d->m_sizeDetermineButton, SIGNAL(clicked()),
this, SLOT(
slotSizeDetermine()) );
1020 connect( d->m_sizeStopButton, SIGNAL(clicked()),
this, SLOT(
slotSizeStop()) );
1021 sizelay->addWidget(d->m_sizeDetermineButton, 0);
1022 sizelay->addWidget(d->m_sizeStopButton, 0);
1023 sizelay->addStretch(10);
1026 if ( isLocal && !hasRoot )
1028 d->m_sizeDetermineButton->setText(
i18n(
"Refresh") );
1032 d->m_sizeStopButton->setEnabled(
false );
1035 if (!d->bMultiple && item.
isLink()) {
1036 l =
new QLabel(
i18n(
"Points to:"), d->m_frame );
1037 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1040 grid->addWidget(d->m_linkTargetLineEdit, curRow++, 2);
1041 connect(d->m_linkTargetLineEdit, SIGNAL(textChanged(
QString)),
this, SLOT(
setDirty()));
1049 l =
new QLabel(
i18n(
"Created:"), d->m_frame );
1050 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1053 grid->addWidget(l, curRow++, 2);
1059 l =
new QLabel(
i18n(
"Modified:"), d->m_frame );
1060 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1063 grid->addWidget(l, curRow++, 2);
1069 l =
new QLabel(
i18n(
"Accessed:"), d->m_frame );
1070 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1073 grid->addWidget(l, curRow++, 2);
1077 if ( isLocal && hasDirs )
1082 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( mp->mountPoint() );
1083 if(info.size() != 0 )
1085 sep =
new KSeparator( Qt::Horizontal, d->m_frame);
1086 grid->addWidget(sep, curRow, 0, 1, 3);
1088 if (mp->mountPoint() !=
"/")
1090 l =
new QLabel(
i18n(
"Mounted on:"), d->m_frame );
1091 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1094 l->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
1095 grid->addWidget( l, curRow++, 2 );
1098 l =
new QLabel(
i18n(
"Device usage:"), d->m_frame );
1099 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1102 grid->addWidget( d->m_capacityBar, curRow++, 2);
1104 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
1112 bool KFilePropsPlugin::enableIconButton()
const
1114 bool iconEnabled =
false;
1132 if ( d->m_lined && !d->m_bFromTemplate )
1134 d->m_lined->setReadOnly( ro );
1147 const int pos = d->oldFileName.lastIndexOf(
'.');
1149 mime =
'*' + d->oldFileName.mid(pos);
1155 QString keditfiletype = QString::fromLatin1(
"keditfiletype");
1161 keditfiletype, keditfiletype ,
properties->window());
1164 void KFilePropsPlugin::slotIconChanged()
1166 d->bIconChanged =
true;
1170 void KFilePropsPlugin::nameFileChanged(
const QString &text )
1176 void KFilePropsPlugin::determineRelativePath(
const QString & path )
1180 if (d->m_sRelativePath.startsWith(
'/'))
1183 if (d->m_sRelativePath.startsWith(
'/'))
1184 d->m_sRelativePath.clear();
1186 d->m_sRelativePath = path;
1195 d->m_capacityBar->setText(
1196 i18nc(
"Available space out of total partition size (percent used)",
"%1 free of %2 (%3% used)",
1199 100 - (
int)(100.0 * kibAvail / kibSize) ));
1201 d->m_capacityBar->setValue(100 - (
int)(100.0 * kibAvail / kibSize));
1209 d->m_sizeLabel->setText(
1210 i18n(
"Calculating... %1 (%2)\n%3, %4",
1213 i18np(
"1 file",
"%1 files", totalFiles),
1214 i18np(
"1 sub-folder",
"%1 sub-folders", totalSubdirs)));
1226 d->m_sizeLabel->setText( QString::fromLatin1(
"%1 (%2)\n%3, %4")
1229 .arg(
i18np(
"1 file",
"%1 files",totalFiles))
1230 .arg(
i18np(
"1 sub-folder",
"%1 sub-folders",totalSubdirs)));
1232 d->m_sizeStopButton->setEnabled(
false);
1234 d->m_sizeDetermineButton->setText(
i18n(
"Refresh") );
1235 d->m_sizeDetermineButton->setEnabled(
true);
1237 delete d->dirSizeUpdateTimer;
1238 d->dirSizeUpdateTimer = 0;
1243 d->m_sizeLabel->setText(
i18n(
"Calculating...") );
1244 kDebug(250) <<
" KFilePropsPlugin::slotSizeDetermine() properties->item()=" <<
properties->
item();
1248 d->dirSizeUpdateTimer =
new QTimer(
this);
1249 connect( d->dirSizeUpdateTimer, SIGNAL(
timeout()),
1251 d->dirSizeUpdateTimer->start(500);
1252 connect( d->dirSizeJob, SIGNAL(result(
KJob*)),
1254 d->m_sizeStopButton->setEnabled(
true);
1255 d->m_sizeDetermineButton->setEnabled(
false);
1258 if ( d->m_capacityBar )
1266 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( mp->mountPoint() );
1267 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
1275 if ( d->dirSizeJob )
1278 d->m_sizeLabel->setText(
i18n(
"At least %1",
1280 d->dirSizeJob->kill();
1283 if ( d->dirSizeUpdateTimer )
1284 d->dirSizeUpdateTimer->stop();
1286 d->m_sizeStopButton->setEnabled(
false);
1287 d->m_sizeDetermineButton->setEnabled(
true);
1302 if ( d->dirSizeJob )
1305 kDebug(250) <<
"KFilePropsPlugin::applyChanges";
1307 if (qobject_cast<QLineEdit*>(d->nameArea))
1311 while ( ! n.isEmpty() && n[n.length()-1].isSpace() )
1312 n.truncate( n.length() - 1 );
1321 kDebug(250) <<
"oldname = " << d->oldName;
1322 kDebug(250) <<
"newname = " << n;
1323 if ( d->oldName != n || d->m_bFromTemplate ) {
1328 if (d->bDesktopFile && !newFileName.endsWith(QLatin1String(
".desktop")) &&
1329 !newFileName.endsWith(QLatin1String(
".kdelnk")))
1330 newFileName +=
".desktop";
1336 if ( !d->m_sRelativePath.isEmpty() )
1340 kDebug(250) <<
"old = " << oldurl.
url();
1343 if ( !d->m_bFromTemplate )
1348 connect( job, SIGNAL(result(
KJob*)),
1353 QEventLoop eventLoop;
1355 &eventLoop, SLOT(
quit()));
1356 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
1361 if ( !d->m_sRelativePath.isEmpty() )
1371 kDebug(250) <<
"KFilePropsPlugin::slotCopyFinished";
1390 if (d->bDesktopFile && !d->m_sRelativePath.isEmpty())
1392 kDebug(250) <<
"KFilePropsPlugin::slotCopyFinished " << d->m_sRelativePath;
1395 kDebug(250) <<
"KFilePropsPlugin::slotCopyFinished path=" << newURL.
path();
1399 if ( d->bKDesktopMode && d->bDesktopFile ) {
1403 if ( d->m_bFromTemplate ) {
1410 cg.writeEntry(
"Name", nameStr );
1415 if (d->m_linkTargetLineEdit && !d->bMultiple) {
1417 const QString newTarget = d->m_linkTargetLineEdit->text();
1418 if (newTarget != item.
linkDest()) {
1419 kDebug(250) <<
"Updating target of symlink to" << newTarget;
1429 if ( d->m_bFromTemplate ) {
1431 KDesktopFile templateResult ( static_cast<KIO::CopyJob*>(job)->srcUrls().first().toLocalFile() );
1439 fileItemList << appLink;
1448 void KFilePropsPlugin::applyIconChanges()
1451 if ( !iconButton || !d->bIconChanged )
1475 if ( str != iconButton->
icon() )
1476 sIcon = iconButton->
icon();
1479 kDebug(250) <<
"**" << path <<
"**";
1482 if ( !sIcon.isEmpty() || QFile::exists(path) )
1485 kDebug(250) <<
"sIcon = " << (sIcon);
1486 kDebug(250) <<
"str = " << (str);
1487 cfg.desktopGroup().writeEntry(
"Icon", sIcon );
1490 cfg.reparseConfiguration();
1491 if ( cfg.desktopGroup().readEntry(
"Icon") != sIcon ) {
1493 "have sufficient access to write to <b>%1</b>.</qt>", path));
1516 class KFilePermissionsPropsPlugin::KFilePermissionsPropsPluginPrivate
1519 KFilePermissionsPropsPluginPrivate()
1522 ~KFilePermissionsPropsPluginPrivate()
1527 QCheckBox *cbRecursive;
1528 QLabel *explanationLabel;
1529 KComboBox *ownerPermCombo, *groupPermCombo, *othersPermCombo;
1530 QCheckBox *extraCheckbox;
1531 mode_t partialPermissions;
1533 bool canChangePermissions;
1535 bool hasExtendedACL;
1538 bool fileSystemSupportsACLs;
1553 #define UniOwner (S_IRUSR|S_IWUSR|S_IXUSR)
1554 #define UniGroup (S_IRGRP|S_IWGRP|S_IXGRP)
1555 #define UniOthers (S_IROTH|S_IWOTH|S_IXOTH)
1556 #define UniRead (S_IRUSR|S_IRGRP|S_IROTH)
1557 #define UniWrite (S_IWUSR|S_IWGRP|S_IWOTH)
1558 #define UniExec (S_IXUSR|S_IXGRP|S_IXOTH)
1559 #define UniSpecial (S_ISUID|S_ISGID|S_ISVTX)
1563 const mode_t KFilePermissionsPropsPlugin::standardPermissions[4] = { 0,
UniRead,
UniRead|
UniWrite, (mode_t)-1 };
1566 const char *KFilePermissionsPropsPlugin::permissionsTexts[4][4] = {
1578 I18N_NOOP(
"Can View/Read & Modify/Write"),
1586 d->cbRecursive = 0L;
1587 d->grpCombo = 0L; d->grpEdit = 0;
1593 bool IamRoot = (geteuid() == 0);
1596 bool isLink = item.
isLink();
1597 bool isDir = item.
isDir();
1598 bool hasDir = item.
isDir();
1600 d->partialPermissions = d->permissions;
1601 d->isIrregular = isIrregular(d->permissions, isDir, isLink);
1602 d->strOwner = item.
user();
1603 d->strGroup = item.
group();
1605 d->extendedACL = item.
ACL();
1607 d->fileSystemSupportsACLs =
false;
1613 KFileItemList::const_iterator it = items.begin();
1614 const KFileItemList::const_iterator kend = items.end();
1615 for ( ++it ; it != kend; ++it )
1618 if (!d->isIrregular)
1619 d->isIrregular |= isIrregular((*it).permissions(),
1620 (*it).isDir() == isDir,
1621 (*it).isLink() == isLink);
1622 d->hasExtendedACL = d->hasExtendedACL || (*it).hasExtendedACL();
1623 if ( (*it).isLink() != isLink )
1625 if ( (*it).isDir() != isDir )
1627 hasDir |= (*it).isDir();
1628 if ( (*it).permissions() != d->permissions )
1630 d->permissions &= (*it).permissions();
1631 d->partialPermissions |= (*it).permissions();
1633 if ( (*it).user() != d->strOwner )
1634 d->strOwner.clear();
1635 if ( (*it).group() != d->strGroup )
1636 d->strGroup.clear();
1650 d->partialPermissions = d->partialPermissions & ~d->permissions;
1652 bool isMyFile =
false;
1654 if (isLocal && !d->strOwner.isEmpty()) {
1655 struct passwd *myself = getpwuid( geteuid() );
1658 isMyFile = (d->strOwner == QString::fromLocal8Bit(myself->pw_name));
1660 kWarning() <<
"I don't exist ?! geteuid=" << geteuid();
1668 d->canChangePermissions = (isMyFile || IamRoot) && (!isLink);
1673 d->m_frame =
new QFrame();
1676 QBoxLayout *box =
new QVBoxLayout( d->m_frame );
1677 box->setMargin( 0 );
1686 gb =
new QGroupBox (
i18n(
"Access Permissions"), d->m_frame );
1687 box->addWidget (gb);
1689 gl =
new QGridLayout (gb);
1690 gl->setColumnStretch(1, 1);
1692 l = d->explanationLabel =
new QLabel(
"", gb );
1694 d->explanationLabel->setText(
i18np(
"This file is a link and does not have permissions.",
1695 "All files are links and do not have permissions.",
1697 else if (!d->canChangePermissions)
1698 d->explanationLabel->setText(
i18n(
"Only the owner can change permissions."));
1699 gl->addWidget(l, 0, 0, 1, 2);
1702 gl->addWidget(lbl, 1, 0, Qt::AlignRight);
1703 l = d->ownerPermCombo =
new KComboBox(gb);
1705 gl->addWidget(l, 1, 1);
1706 connect(l, SIGNAL(activated(
int)),
this, SIGNAL(
changed()));
1707 l->setWhatsThis(
i18n(
"Specifies the actions that the owner is allowed to do."));
1710 gl->addWidget(lbl, 2, 0, Qt::AlignRight);
1711 l = d->groupPermCombo =
new KComboBox(gb);
1713 gl->addWidget(l, 2, 1);
1714 connect(l, SIGNAL(activated(
int)),
this, SIGNAL(
changed()));
1715 l->setWhatsThis(
i18n(
"Specifies the actions that the members of the group are allowed to do."));
1718 gl->addWidget(lbl, 3, 0, Qt::AlignRight);
1719 l = d->othersPermCombo =
new KComboBox(gb);
1721 gl->addWidget(l, 3, 1);
1722 connect(l, SIGNAL(activated(
int)),
this, SIGNAL(
changed()));
1723 l->setWhatsThis(
i18n(
"Specifies the actions that all users, who are neither "
1724 "owner nor in the group, are allowed to do."));
1727 l = d->extraCheckbox =
new QCheckBox(hasDir ?
1728 i18n(
"Only own&er can rename and delete folder content") :
1729 i18n(
"Is &executable"),
1731 connect( d->extraCheckbox, SIGNAL(clicked()),
this, SIGNAL(
changed()) );
1732 gl->addWidget(l, 4, 1);
1733 l->setWhatsThis(hasDir ?
i18n(
"Enable this option to allow only the folder's owner to "
1734 "delete or rename the contained files and folders. Other "
1735 "users can only add new files, which requires the 'Modify "
1736 "Content' permission.")
1737 :
i18n(
"Enable this option to mark the file as executable. This only makes "
1738 "sense for programs and scripts. It is required when you want to "
1741 QLayoutItem *spacer =
new QSpacerItem(0, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
1742 gl->addItem(spacer, 5, 0, 1, 3);
1745 gl->addWidget(pbAdvancedPerm, 6, 0, 1, 2, Qt::AlignRight);
1746 connect(pbAdvancedPerm, SIGNAL(clicked()),
this, SLOT(slotShowAdvancedPermissions()));
1749 d->extraCheckbox = 0;
1754 box->addWidget (gb);
1756 gl =
new QGridLayout (gb);
1757 gl->addItem(
new QSpacerItem(0, 10), 0, 0);
1761 gl->addWidget (l, 1, 0, Qt::AlignRight);
1768 int i, maxEntries = 1000;
1769 struct passwd *user;
1774 if (IamRoot && isLocal)
1777 KCompletion *kcom = d->usrEdit->completionObject();
1780 for (i=0; ((user = getpwent()) != 0L) && (i < maxEntries); ++i)
1781 kcom->
addItem(QString::fromLatin1(user->pw_name));
1785 d->usrEdit->setText(d->strOwner);
1786 gl->addWidget(d->usrEdit, 1, 1);
1787 connect( d->usrEdit, SIGNAL(textChanged(
QString)),
1792 l =
new QLabel(d->strOwner, gb);
1793 gl->addWidget(l, 1, 1);
1800 user = getpwuid(geteuid());
1802 strUser = user->pw_name;
1804 #ifdef HAVE_GETGROUPLIST
1808 QVarLengthArray<int> groups;
1810 QVarLengthArray<gid_t> groups;
1812 if (getgrouplist(strUser, user->pw_gid, NULL, &groupCount) < 0) {
1813 groups.resize(groupCount);
1815 getgrouplist(strUser, user->pw_gid, groups.data(), &groupCount);
1820 for (i = 0; i < groupCount; i++) {
1821 struct group *mygroup = getgrgid(groups[i]);
1823 groupList += QString::fromLocal8Bit(mygroup->gr_name);
1825 #endif // HAVE_GETGROUPLIST
1827 bool isMyGroup = groupList.contains(d->strGroup);
1833 groupList += d->strGroup;
1836 gl->addWidget (l, 2, 0, Qt::AlignRight);
1844 if (IamRoot && isLocal)
1849 d->grpEdit->setCompletionObject(kcom,
true);
1850 d->grpEdit->setAutoDeleteCompletionObject(
true );
1852 d->grpEdit->setText(d->strGroup);
1853 gl->addWidget(d->grpEdit, 2, 1);
1854 connect( d->grpEdit, SIGNAL(textChanged(
QString)),
1857 else if ((groupList.count() > 1) && isMyFile && isLocal)
1860 d->grpCombo->setObjectName(QLatin1String(
"combogrouplist"));
1861 d->grpCombo->addItems(groupList);
1862 d->grpCombo->setCurrentIndex(groupList.indexOf(d->strGroup));
1863 gl->addWidget(d->grpCombo, 2, 1);
1864 connect( d->grpCombo, SIGNAL(activated(
int)),
1869 l =
new QLabel(d->strGroup, gb);
1870 gl->addWidget(l, 2, 1);
1873 gl->setColumnStretch(2, 10);
1876 if ( hasDir && !isLink && !isTrash )
1878 d->cbRecursive =
new QCheckBox(
i18n(
"Apply changes to all subfolders and their contents"), d->m_frame );
1879 connect( d->cbRecursive, SIGNAL(clicked()),
this, SIGNAL(
changed()) );
1880 box->addWidget( d->cbRecursive );
1883 updateAccessControls();
1889 enableAccessControls(
false);
1890 if ( pbAdvancedPerm)
1891 pbAdvancedPerm->setEnabled(
false);
1894 box->addStretch (10);
1897 #ifdef HAVE_POSIX_ACL
1898 static bool fileSystemSupportsACL(
const QByteArray& path )
1900 bool fileSystemSupportsACLs =
false;
1903 fileSystemSupportsACLs = ( statfs( path.data(), &buf ) == 0 ) && ( buf.f_flags & MNT_ACLS );
1905 fileSystemSupportsACLs =
1906 getxattr( path.data(),
"system.posix_acl_access", NULL, 0 ) >= 0 || errno == ENODATA;
1908 return fileSystemSupportsACLs;
1913 void KFilePermissionsPropsPlugin::slotShowAdvancedPermissions() {
1917 dlg.setModal(
true );
1918 dlg.setCaption(
i18n(
"Advanced Permissions") );
1926 QVBoxLayout *vbox =
new QVBoxLayout(mainw);
1929 vbox->addWidget(gb);
1931 gl =
new QGridLayout (gb);
1932 gl->addItem(
new QSpacerItem(0, 10), 0, 0);
1934 QVector<QWidget*> theNotSpecials;
1937 gl->addWidget(l, 1, 0);
1938 theNotSpecials.append( l );
1944 gl->addWidget (l, 1, 1);
1945 theNotSpecials.append( l );
1948 readWhatsThis =
i18n(
"This flag allows viewing the content of the folder.");
1950 readWhatsThis =
i18n(
"The Read flag allows viewing the content of the file.");
1951 l->setWhatsThis(readWhatsThis);
1954 l =
new QLabel(
i18n(
"Write\nEntries"), gb );
1957 gl->addWidget (l, 1, 2);
1958 theNotSpecials.append( l );
1961 writeWhatsThis =
i18n(
"This flag allows adding, renaming and deleting of files. "
1962 "Note that deleting and renaming can be limited using the Sticky flag.");
1964 writeWhatsThis =
i18n(
"The Write flag allows modifying the content of the file.");
1965 l->setWhatsThis(writeWhatsThis);
1969 l =
new QLabel(
i18nc(
"Enter folder",
"Enter"), gb );
1970 execWhatsThis =
i18n(
"Enable this flag to allow entering the folder.");
1974 execWhatsThis =
i18n(
"Enable this flag to allow executing the file as a program.");
1976 l->setWhatsThis(execWhatsThis);
1977 theNotSpecials.append( l );
1979 QSize size = l->sizeHint();
1980 size.setWidth(size.width() + 15);
1981 l->setFixedSize(size);
1982 gl->addWidget (l, 1, 3);
1985 gl->addWidget(l, 1, 4, 1, 2);
1988 specialWhatsThis =
i18n(
"Special flag. Valid for the whole folder, the exact "
1989 "meaning of the flag can be seen in the right hand column.");
1991 specialWhatsThis =
i18n(
"Special flag. The exact meaning of the flag can be seen "
1992 "in the right hand column.");
1993 l->setWhatsThis(specialWhatsThis);
1996 gl->addWidget (cl[0], 2, 0);
1997 theNotSpecials.append( cl[0] );
2000 gl->addWidget (cl[1], 3, 0);
2001 theNotSpecials.append( cl[1] );
2004 gl->addWidget (cl[2], 4, 0);
2005 theNotSpecials.append( cl[2] );
2008 gl->addWidget(l, 2, 5);
2011 setUidWhatsThis =
i18n(
"If this flag is set, the owner of this folder will be "
2012 "the owner of all new files.");
2014 setUidWhatsThis =
i18n(
"If this file is an executable and the flag is set, it will "
2015 "be executed with the permissions of the owner.");
2016 l->setWhatsThis(setUidWhatsThis);
2019 gl->addWidget(l, 3, 5);
2022 setGidWhatsThis =
i18n(
"If this flag is set, the group of this folder will be "
2023 "set for all new files.");
2025 setGidWhatsThis =
i18n(
"If this file is an executable and the flag is set, it will "
2026 "be executed with the permissions of the group.");
2027 l->setWhatsThis(setGidWhatsThis);
2029 l =
new QLabel(
i18nc(
"File permission",
"Sticky"), gb);
2030 gl->addWidget(l, 4, 5);
2033 stickyWhatsThis =
i18n(
"If the Sticky flag is set on a folder, only the owner "
2034 "and root can delete or rename files. Otherwise everybody "
2035 "with write permissions can do this.");
2037 stickyWhatsThis =
i18n(
"The Sticky flag on a file is ignored on Linux, but may "
2038 "be used on some systems");
2039 l->setWhatsThis(stickyWhatsThis);
2041 mode_t aPermissions, aPartialPermissions;
2042 mode_t dummy1, dummy2;
2044 if (!d->isIrregular) {
2047 getPermissionMasks(aPartialPermissions,
2054 getPermissionMasks(dummy1,
2055 aPartialPermissions,
2061 aPartialPermissions = 0;
2066 aPermissions = d->permissions;
2067 aPartialPermissions = d->partialPermissions;
2071 QCheckBox *cba[3][4];
2072 for (
int row = 0; row < 3 ; ++row) {
2073 for (
int col = 0; col < 4; ++col) {
2074 QCheckBox *cb =
new QCheckBox(gb);
2075 if ( col != 3 ) theNotSpecials.append( cb );
2077 cb->setChecked(aPermissions & fperm[row][col]);
2078 if ( aPartialPermissions & fperm[row][col] )
2081 cb->setCheckState(Qt::PartiallyChecked);
2083 else if (d->cbRecursive && d->cbRecursive->isChecked())
2086 cb->setEnabled( d->canChangePermissions );
2087 gl->addWidget (cb, row+2, col+1);
2090 cb->setWhatsThis(readWhatsThis);
2093 cb->setWhatsThis(writeWhatsThis);
2096 cb->setWhatsThis(execWhatsThis);
2101 cb->setWhatsThis(setUidWhatsThis);
2104 cb->setWhatsThis(setGidWhatsThis);
2107 cb->setWhatsThis(stickyWhatsThis);
2114 gl->setColumnStretch(6, 10);
2116 #ifdef HAVE_POSIX_ACL
2117 KACLEditWidget *extendedACLs = 0;
2122 d->fileSystemSupportsACLs = fileSystemSupportsACL( path );
2124 if ( d->fileSystemSupportsACLs ) {
2125 std::for_each( theNotSpecials.begin(), theNotSpecials.end(), std::mem_fun( &QWidget::hide ) );
2126 extendedACLs =
new KACLEditWidget( mainw );
2127 vbox->addWidget(extendedACLs);
2128 if ( d->extendedACL.isValid() && d->extendedACL.isExtended() )
2129 extendedACLs->setACL( d->extendedACL );
2131 extendedACLs->setACL(
KACL( aPermissions ) );
2133 if ( d->defaultACL.isValid() )
2134 extendedACLs->setDefaultACL( d->defaultACL );
2137 extendedACLs->setAllowDefaults(
true );
2140 dlg.setMainWidget( mainw );
2141 if (dlg.exec() != KDialog::Accepted)
2144 mode_t andPermissions = mode_t(~0);
2145 mode_t orPermissions = 0;
2146 for (
int row = 0; row < 3; ++row)
2147 for (
int col = 0; col < 4; ++col) {
2148 switch (cba[row][col]->checkState())
2151 orPermissions |= fperm[row][col];
2154 andPermissions &= ~fperm[row][col];
2161 d->isIrregular =
false;
2163 KFileItemList::const_iterator it = items.begin();
2164 const KFileItemList::const_iterator kend = items.end();
2165 for ( ; it != kend; ++it ) {
2166 if (isIrregular(((*it).permissions() & andPermissions) | orPermissions,
2167 (*it).isDir(), (*it).isLink())) {
2168 d->isIrregular =
true;
2173 d->permissions = orPermissions;
2174 d->partialPermissions = andPermissions;
2176 #ifdef HAVE_POSIX_ACL
2178 if ( extendedACLs ) {
2179 d->extendedACL = extendedACLs->getACL();
2180 d->defaultACL = extendedACLs->getDefaultACL();
2181 d->hasExtendedACL = d->extendedACL.isExtended() || d->defaultACL.isValid();
2182 d->permissions = d->extendedACL.basePermissions();
2183 d->permissions |= ( andPermissions | orPermissions ) & ( S_ISUID|S_ISGID|S_ISVTX );
2187 updateAccessControls();
2207 void KFilePermissionsPropsPlugin::setComboContent(
QComboBox *combo, PermissionsTarget target,
2208 mode_t permissions, mode_t partial) {
2214 combo->addItem(
i18n(
"Link"));
2215 combo->setCurrentIndex(0);
2219 mode_t tMask = permissionsMasks[target];
2221 for (textIndex = 0; standardPermissions[textIndex] != (mode_t)-1; textIndex++) {
2222 if ((standardPermissions[textIndex]&tMask) == (permissions&tMask&(
UniRead|
UniWrite)))
2225 Q_ASSERT(standardPermissions[textIndex] != (mode_t)-1);
2227 for (
int i = 0; permissionsTexts[(int)d->pmode][i]; i++)
2228 combo->addItem(
i18n(permissionsTexts[(
int)d->pmode][i]));
2230 if (partial & tMask & ~
UniExec) {
2231 combo->addItem(
i18n(
"Varying (No Change)"));
2232 combo->setCurrentIndex(3);
2235 combo->setCurrentIndex(textIndex);
2240 bool KFilePermissionsPropsPlugin::isIrregular(mode_t permissions,
bool isDir,
bool isLink) {
2244 mode_t p = permissions;
2245 if (p & (S_ISUID | S_ISGID))
2252 if ((p0 != 0) && (p0 != (S_IRUSR | S_IXUSR)) && (p0 != UniOwner))
2255 if ((p0 != 0) && (p0 != (S_IRGRP | S_IXGRP)) && (p0 != UniGroup))
2258 if ((p0 != 0) && (p0 != (S_IROTH | S_IXOTH)) && (p0 != UniOthers))
2267 bool usrXPossible = !p0;
2269 if ((p0 == S_IXUSR) || (p0 == (S_IWUSR | S_IXUSR)))
2271 usrXPossible =
true;
2273 else if (p0 == S_IWUSR)
2277 bool grpXPossible = !p0;
2279 if ((p0 == S_IXGRP) || (p0 == (S_IWGRP | S_IXGRP)))
2281 grpXPossible =
true;
2283 else if (p0 == S_IWGRP)
2286 grpXPossible =
true;
2289 bool othXPossible = !p0;
2291 if ((p0 == S_IXOTH) || (p0 == (S_IWOTH | S_IXOTH)))
2293 othXPossible =
true;
2295 else if (p0 == S_IWOTH)
2299 return (p &
UniExec) && !(usrXPossible && grpXPossible && othXPossible);
2303 void KFilePermissionsPropsPlugin::enableAccessControls(
bool enable) {
2304 d->ownerPermCombo->setEnabled(enable);
2305 d->groupPermCombo->setEnabled(enable);
2306 d->othersPermCombo->setEnabled(enable);
2307 if (d->extraCheckbox)
2308 d->extraCheckbox->setEnabled(enable);
2309 if ( d->cbRecursive )
2310 d->cbRecursive->setEnabled(enable);
2314 void KFilePermissionsPropsPlugin::updateAccessControls() {
2316 d->permissions, d->partialPermissions);
2318 d->permissions, d->partialPermissions);
2320 d->permissions, d->partialPermissions);
2324 enableAccessControls(
false);
2327 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2328 if (d->canChangePermissions)
2329 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2330 i18np(
"This file uses advanced permissions",
2331 "These files use advanced permissions.",
2333 if (d->partialPermissions &
UniExec) {
2334 d->extraCheckbox->setTristate();
2335 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
2338 d->extraCheckbox->setTristate(
false);
2339 d->extraCheckbox->setChecked(d->permissions &
UniExec);
2343 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2346 if ( d->cbRecursive )
2347 d->cbRecursive->setEnabled( d->canChangePermissions && !d->isIrregular );
2349 if (d->canChangePermissions)
2350 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2351 i18np(
"This folder uses advanced permissions.",
2352 "These folders use advanced permissions.",
2354 if (d->partialPermissions & S_ISVTX) {
2355 d->extraCheckbox->setTristate();
2356 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
2359 d->extraCheckbox->setTristate(
false);
2360 d->extraCheckbox->setChecked(d->permissions & S_ISVTX);
2364 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2365 if (d->canChangePermissions)
2366 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2367 i18n(
"These files use advanced permissions.") :
"");
2369 if (d->partialPermissions & S_ISVTX) {
2370 d->extraCheckbox->setTristate();
2371 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
2374 d->extraCheckbox->setTristate(
false);
2375 d->extraCheckbox->setChecked(d->permissions & S_ISVTX);
2382 void KFilePermissionsPropsPlugin::getPermissionMasks(mode_t &andFilePermissions,
2383 mode_t &andDirPermissions,
2384 mode_t &orFilePermissions,
2385 mode_t &orDirPermissions) {
2387 andDirPermissions = mode_t(~(S_ISUID|S_ISGID));
2388 orFilePermissions = 0;
2389 orDirPermissions = 0;
2393 mode_t m = standardPermissions[d->ownerPermCombo->currentIndex()];
2394 if (m != (mode_t) -1) {
2396 if ((m & UniOwner) &&
2398 ((d->pmode ==
PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
2399 andFilePermissions &= ~(S_IRUSR | S_IWUSR);
2401 andFilePermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2402 if ((m & S_IRUSR) && (d->extraCheckbox->checkState() == Qt::Checked))
2403 orFilePermissions |= S_IXUSR;
2408 orDirPermissions |= S_IXUSR;
2409 andDirPermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2412 m = standardPermissions[d->groupPermCombo->currentIndex()];
2413 if (m != (mode_t) -1) {
2415 if ((m & UniGroup) &&
2417 ((d->pmode ==
PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
2418 andFilePermissions &= ~(S_IRGRP | S_IWGRP);
2420 andFilePermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2421 if ((m & S_IRGRP) && (d->extraCheckbox->checkState() == Qt::Checked))
2422 orFilePermissions |= S_IXGRP;
2427 orDirPermissions |= S_IXGRP;
2428 andDirPermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2431 m = d->othersPermCombo->currentIndex() >= 0 ? standardPermissions[d->othersPermCombo->currentIndex()] : (mode_t)-1;
2432 if (m != (mode_t) -1) {
2434 if ((m & UniOthers) &&
2436 ((d->pmode ==
PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
2437 andFilePermissions &= ~(S_IROTH | S_IWOTH);
2439 andFilePermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2440 if ((m & S_IROTH) && (d->extraCheckbox->checkState() == Qt::Checked))
2441 orFilePermissions |= S_IXOTH;
2446 orDirPermissions |= S_IXOTH;
2447 andDirPermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2451 (d->extraCheckbox->checkState() != Qt::PartiallyChecked)) {
2452 andDirPermissions &= ~S_ISVTX;
2453 if (d->extraCheckbox->checkState() == Qt::Checked)
2454 orDirPermissions |= S_ISVTX;
2460 mode_t orFilePermissions;
2461 mode_t orDirPermissions;
2462 mode_t andFilePermissions;
2463 mode_t andDirPermissions;
2465 if (!d->canChangePermissions)
2468 if (!d->isIrregular)
2469 getPermissionMasks(andFilePermissions,
2474 orFilePermissions = d->permissions;
2475 andFilePermissions = d->partialPermissions;
2476 orDirPermissions = d->permissions;
2477 andDirPermissions = d->partialPermissions;
2482 owner = d->usrEdit->text();
2484 group = d->grpEdit->text();
2485 else if (d->grpCombo)
2486 group = d->grpCombo->currentText();
2488 if (owner == d->strOwner)
2491 if (group == d->strGroup)
2494 bool recursive = d->cbRecursive && d->cbRecursive->isChecked();
2495 bool permissionChange =
false;
2499 KFileItemList::const_iterator it = items.begin();
2500 const KFileItemList::const_iterator kend = items.end();
2501 for ( ; it != kend; ++it ) {
2502 if ((*it).isDir()) {
2504 if ((*it).permissions() != (((*it).permissions() & andDirPermissions) | orDirPermissions))
2505 permissionChange =
true;
2507 else if ((*it).isFile()) {
2509 if ((*it).permissions() != (((*it).permissions() & andFilePermissions) | orFilePermissions))
2510 permissionChange =
true;
2517 if (owner.isEmpty() && group.isEmpty() && !recursive
2518 && !permissionChange && !ACLChange && !defaultACLChange)
2522 if (files.count() > 0) {
2523 job =
KIO::chmod( files, orFilePermissions, ~andFilePermissions,
2524 owner, group,
false );
2525 if ( ACLChange && d->fileSystemSupportsACLs )
2526 job->
addMetaData(
"ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():
"ACL_DELETE" );
2527 if ( defaultACLChange && d->fileSystemSupportsACLs )
2528 job->
addMetaData(
"DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():
"ACL_DELETE" );
2530 connect( job, SIGNAL(result(
KJob*)),
2531 SLOT(slotChmodResult(
KJob*)) );
2532 QEventLoop eventLoop;
2534 &eventLoop, SLOT(
quit()));
2535 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
2537 if (dirs.count() > 0) {
2538 job =
KIO::chmod( dirs, orDirPermissions, ~andDirPermissions,
2539 owner, group, recursive );
2540 if ( ACLChange && d->fileSystemSupportsACLs )
2541 job->
addMetaData(
"ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():
"ACL_DELETE" );
2542 if ( defaultACLChange && d->fileSystemSupportsACLs )
2543 job->
addMetaData(
"DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():
"ACL_DELETE" );
2545 connect( job, SIGNAL(result(
KJob*)),
2546 SLOT(slotChmodResult(
KJob*)) );
2547 QEventLoop eventLoop;
2549 &eventLoop, SLOT(
quit()));
2550 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
2554 void KFilePermissionsPropsPlugin::slotChmodResult(
KJob * job )
2556 kDebug(250) <<
"KFilePermissionsPropsPlugin::slotChmodResult";
2566 class KUrlPropsPlugin::KUrlPropsPluginPrivate
2569 KUrlPropsPluginPrivate()
2572 ~KUrlPropsPluginPrivate()
2584 d->m_frame =
new QFrame();
2586 QVBoxLayout *layout =
new QVBoxLayout(d->m_frame);
2587 layout->setMargin(0);
2590 l =
new QLabel( d->m_frame );
2591 l->setObjectName( QLatin1String(
"Label_1" ) );
2592 l->setText(
i18n(
"URL:") );
2593 layout->addWidget(l, Qt::AlignRight);
2596 layout->addWidget(d->URLEdit);
2603 if ( !f.open( QIODevice::ReadOnly ) ) {
2612 if (!d->URLStr.isEmpty()) {
2613 d->URLEdit->setUrl(
KUrl(d->URLStr) );
2617 connect( d->URLEdit, SIGNAL(textChanged(
QString)),
2620 layout->addStretch (1);
2635 if ( _items.count() != 1 )
2650 return config.hasLinkType();
2663 if ( !f.open( QIODevice::ReadWrite ) ) {
2665 "sufficient access to write to <b>%1</b>.</qt>", path));
2672 dg.
writeEntry(
"Type", QString::fromLatin1(
"Link"));
2692 class KDevicePropsPlugin::KDevicePropsPluginPrivate
2695 KDevicePropsPluginPrivate()
2698 ~KDevicePropsPluginPrivate()
2702 bool isMounted()
const {
2703 const QString dev = device->currentText();
2710 QLabel *m_freeSpaceLabel;
2711 QProgressBar *m_freeSpaceBar;
2715 QCheckBox* readonly;
2722 d->m_frame =
new QFrame();
2728 for(KMountPoint::List::ConstIterator it = mountPoints.begin();
2729 it != mountPoints.end(); ++it)
2732 QString mountPoint = mp->mountPoint();
2733 QString device = mp->mountedFrom();
2734 kDebug()<<
"mountPoint :"<<mountPoint<<
" device :"<<device<<
" mp->mountType() :"<<mp->mountType();
2736 if ((mountPoint !=
"-") && (mountPoint !=
"none") && !mountPoint.isEmpty()
2737 && device !=
"none")
2739 devices.append( device + QString::fromLatin1(
" (")
2740 + mountPoint + QString::fromLatin1(
")") );
2741 d->m_devicelist.append(device);
2742 d->mountpointlist.append(mountPoint);
2746 QGridLayout *layout =
new QGridLayout( d->m_frame );
2748 layout->setMargin(0);
2749 layout->setColumnStretch(1, 1);
2752 label =
new QLabel( d->m_frame );
2753 label->setText( devices.count() == 0 ?
2754 i18n(
"Device (/dev/fd0):") :
2756 layout->addWidget(label, 0, 0, Qt::AlignRight);
2758 d->device =
new KComboBox( d->m_frame );
2759 d->device->setObjectName( QLatin1String(
"ComboBox_device" ) );
2760 d->device->setEditable(
true );
2761 d->device->addItems( devices );
2762 layout->addWidget(d->device, 0, 1);
2763 connect( d->device, SIGNAL(activated(
int)),
2764 this, SLOT(slotActivated(
int)) );
2766 d->readonly =
new QCheckBox( d->m_frame );
2767 d->readonly->setObjectName( QLatin1String(
"CheckBox_readonly" ) );
2768 d->readonly->setText(
i18n(
"Read only") );
2769 layout->addWidget(d->readonly, 1, 1);
2771 label =
new QLabel( d->m_frame );
2772 label->setText(
i18n(
"File system:") );
2773 layout->addWidget(label, 2, 0, Qt::AlignRight);
2776 layout->addWidget(fileSystem, 2, 1);
2778 label =
new QLabel( d->m_frame );
2779 label->setText( devices.count()==0 ?
2780 i18n(
"Mount point (/mnt/floppy):") :
2781 i18n(
"Mount point:"));
2782 layout->addWidget(label, 3, 0, Qt::AlignRight);
2784 d->mountpoint =
new QLabel( d->m_frame );
2785 d->mountpoint->setObjectName( QLatin1String(
"LineEdit_mountpoint" ) );
2787 layout->addWidget(d->mountpoint, 3, 1);
2790 d->m_freeSpaceText =
new QLabel(
i18n(
"Device usage:"), d->m_frame );
2791 layout->addWidget(d->m_freeSpaceText, 4, 0, Qt::AlignRight);
2793 d->m_freeSpaceLabel =
new QLabel( d->m_frame );
2794 layout->addWidget( d->m_freeSpaceLabel, 4, 1 );
2796 d->m_freeSpaceBar =
new QProgressBar( d->m_frame );
2797 d->m_freeSpaceBar->setObjectName(
"freeSpaceBar" );
2798 layout->addWidget(d->m_freeSpaceBar, 5, 0, 1, 2);
2801 d->m_freeSpaceText->hide();
2802 d->m_freeSpaceLabel->hide();
2803 d->m_freeSpaceBar->hide();
2806 layout->addWidget(sep, 6, 0, 1, 2);
2808 layout->setRowStretch(7, 1);
2817 if ( !f.open( QIODevice::ReadOnly ) )
2825 bool ro = config.
readEntry(
"ReadOnly",
false );
2827 fileSystem->setText(config.
readEntry(
"FSType"));
2829 d->device->setEditText( deviceStr );
2830 if ( !deviceStr.isEmpty() ) {
2832 int index = d->m_devicelist.indexOf(deviceStr);
2836 slotActivated( index );
2840 if ( !mountPointStr.isEmpty() )
2842 d->mountpoint->setText( mountPointStr );
2846 d->readonly->setChecked( ro );
2848 connect( d->device, SIGNAL(activated(
int)),
2850 connect( d->device, SIGNAL(textChanged(
QString)),
2852 connect( d->readonly, SIGNAL(toggled(
bool)),
2855 connect( d->device, SIGNAL(textChanged(
QString)),
2856 this, SLOT(slotDeviceChanged()) );
2869 void KDevicePropsPlugin::updateInfo()
2872 d->m_freeSpaceText->hide();
2873 d->m_freeSpaceLabel->hide();
2874 d->m_freeSpaceBar->hide();
2876 if (!d->mountpoint->text().isEmpty() && d->isMounted()) {
2877 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( d->mountpoint->text() );
2878 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
2882 void KDevicePropsPlugin::slotActivated(
int index )
2886 if (index < d->m_devicelist.count()) {
2888 d->device->setEditText(d->m_devicelist[index]);
2889 d->mountpoint->setText(d->mountpointlist[index]);
2895 void KDevicePropsPlugin::slotDeviceChanged()
2898 int index = d->m_devicelist.indexOf( d->device->currentText() );
2900 d->mountpoint->setText( d->mountpointlist[index] );
2902 d->mountpoint->setText(
QString() );
2907 void KDevicePropsPlugin::slotFoundMountPoint(
const QString&,
2912 d->m_freeSpaceText->show();
2913 d->m_freeSpaceLabel->show();
2915 const int percUsed = kibSize != 0 ? (100 - (int)(100.0 * kibAvail / kibSize)) : 100;
2917 d->m_freeSpaceLabel->setText(
2918 i18nc(
"Available space out of total partition size (percent used)",
"%1 free of %2 (%3% used)",
2923 d->m_freeSpaceBar->setRange(0, 100);
2924 d->m_freeSpaceBar->setValue(percUsed);
2925 d->m_freeSpaceBar->show();
2930 if ( _items.count() != 1 )
2945 return config.hasDeviceType();
2956 if ( !f.open( QIODevice::ReadWrite ) )
2959 "access to write to <b>%1</b>.</qt>", path));
2966 config.
writeEntry(
"Type", QString::fromLatin1(
"FSDevice") );
2968 config.
writeEntry(
"Dev", d->device->currentText() );
2969 config.
writeEntry(
"MountPoint", d->mountpoint->text() );
2971 config.
writeEntry(
"ReadOnly", d->readonly->isChecked() );
2983 class KDesktopPropsPlugin::KDesktopPropsPluginPrivate
2986 KDesktopPropsPluginPrivate()
2987 : w( new Ui_KPropertiesDesktopBase )
2988 , m_frame( new
QFrame() )
2991 ~KDesktopPropsPluginPrivate()
2995 Ui_KPropertiesDesktopBase* w;
3003 bool m_terminalBool;
3012 d->w->setupUi(d->m_frame);
3022 d->w->nameEdit->hide();
3023 d->w->nameLabel->hide();
3027 d->w->pathEdit->lineEdit()->setAcceptDrops(
false);
3029 connect( d->w->nameEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3030 connect( d->w->genNameEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3031 connect( d->w->commentEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3032 connect( d->w->commandEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3033 connect( d->w->pathEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3035 connect( d->w->browseButton, SIGNAL(clicked()),
this, SLOT(
slotBrowseExec()) );
3036 connect( d->w->addFiletypeButton, SIGNAL(clicked()),
this, SLOT(
slotAddFiletype()) );
3037 connect( d->w->delFiletypeButton, SIGNAL(clicked()),
this, SLOT(
slotDelFiletype()) );
3038 connect( d->w->advancedButton, SIGNAL(clicked()),
this, SLOT(
slotAdvanced()) );
3049 if ( !f.open( QIODevice::ReadOnly ) )
3059 if (commandStr.startsWith(QLatin1String(
"ksystraycmd ")))
3061 commandStr.remove(0, 12);
3062 d->m_systrayBool =
true;
3065 d->m_systrayBool =
false;
3067 d->m_origCommandStr = commandStr;
3069 d->m_terminalBool = config.
readEntry(
"Terminal",
false );
3070 d->m_terminalOptionStr = config.
readEntry(
"TerminalOptions" );
3071 d->m_suidBool = config.
readEntry(
"X-KDE-SubstituteUID",
false );
3072 d->m_suidUserStr = config.
readEntry(
"X-KDE-Username" );
3073 if( config.
hasKey(
"StartupNotify" ))
3074 d->m_startupBool = config.
readEntry(
"StartupNotify",
true );
3076 d->m_startupBool = config.
readEntry(
"X-KDE-StartupNotify",
true );
3077 d->m_dbusStartupType = config.
readEntry(
"X-DBUS-StartupType").toLower();
3080 d->m_dbusServiceName = config.
readEntry(
"X-DBUS-ServiceName");
3084 if ( nameStr.isEmpty() || bKDesktopMode ) {
3090 if ( !bKDesktopMode )
3091 d->w->nameEdit->setText(nameStr);
3093 d->w->genNameEdit->setText( genNameStr );
3094 d->w->commentEdit->setText( commentStr );
3095 d->w->commandEdit->setText( commandStr );
3096 d->w->pathEdit->lineEdit()->setText( pathStr );
3102 for(QStringList::ConstIterator it = mimeTypes.begin();
3103 it != mimeTypes.end(); )
3108 if (it != mimeTypes.end())
3111 (*it).toInt(&numeric);
3120 QTreeWidgetItem *item =
new QTreeWidgetItem();
3121 item->setText(0, p->
name());
3122 item->setText(1, p->
comment());
3123 item->setText(2, preference);
3124 d->w->filetypeList->addTopLevelItem(item);
3127 d->w->filetypeList->resizeColumnToContents(0);
3139 i18n(
"Select one or more file types to add:"),
3146 if (dlg.exec() == KDialog::Accepted)
3148 foreach(
const QString &mimetype, dlg.chooser()->mimeTypes())
3155 int count = d->w->filetypeList->topLevelItemCount();
3156 for (
int i = 0; !found && i < count; ++i) {
3157 if (d->w->filetypeList->topLevelItem(i)->text(0) ==
mimetype) {
3162 QTreeWidgetItem *item =
new QTreeWidgetItem();
3163 item->setText(0, p->
name());
3164 item->setText(1, p->
comment());
3165 d->w->filetypeList->addTopLevelItem(item);
3167 d->w->filetypeList->resizeColumnToContents(0);
3175 QTreeWidgetItem *cur = d->w->filetypeList->currentItem();
3182 void KDesktopPropsPlugin::checkCommandChanged()
3187 d->m_origCommandStr = d->w->commandEdit->text();
3188 d->m_dbusStartupType.clear();
3189 d->m_dbusServiceName.clear();
3195 kDebug(250) <<
"KDesktopPropsPlugin::applyChanges";
3206 if ( !f.open( QIODevice::ReadWrite ) ) {
3208 "sufficient access to write to <b>%1</b>.</qt>", path));
3215 checkCommandChanged();
3219 config.
writeEntry(
"Type", QString::fromLatin1(
"Application"));
3220 config.
writeEntry(
"Comment", d->w->commentEdit->text() );
3222 config.
writeEntry(
"GenericName", d->w->genNameEdit->text() );
3225 if (d->m_systrayBool)
3226 config.
writeEntry(
"Exec", d->w->commandEdit->text().prepend(
"ksystraycmd ") );
3228 config.
writeEntry(
"Exec", d->w->commandEdit->text() );
3229 config.
writeEntry(
"Path", d->w->pathEdit->lineEdit()->text() );
3233 int count = d->w->filetypeList->topLevelItemCount();
3234 for (
int i = 0; i < count; ++i) {
3235 QTreeWidgetItem *item = d->w->filetypeList->topLevelItem(i);
3236 QString preference = item->text(2);
3237 mimeTypes.append(item->text(0));
3238 if (!preference.isEmpty())
3239 mimeTypes.append(preference);
3245 if ( !d->w->nameEdit->isHidden() ) {
3246 QString nameStr = d->w->nameEdit->text();
3251 config.
writeEntry(
"Terminal", d->m_terminalBool);
3252 config.
writeEntry(
"TerminalOptions", d->m_terminalOptionStr);
3253 config.
writeEntry(
"X-KDE-SubstituteUID", d->m_suidBool);
3254 config.
writeEntry(
"X-KDE-Username", d->m_suidUserStr);
3255 config.
writeEntry(
"StartupNotify", d->m_startupBool);
3256 config.
writeEntry(
"X-DBUS-StartupType", d->m_dbusStartupType);
3257 config.
writeEntry(
"X-DBUS-ServiceName", d->m_dbusServiceName);
3262 bool updateNeeded = !sycocaPath.startsWith(
'/');
3266 updateNeeded = !sycocaPath.startsWith(
'/');
3287 d->w->commandEdit->setText( path );
3293 dlg.setObjectName(
"KPropertiesDesktopAdv" );
3294 dlg.setModal(
true );
3298 Ui_KPropertiesDesktopAdvBase w;
3303 checkCommandChanged();
3309 QString::fromLatin1(
"konsole"));
3311 bool terminalCloseBool =
false;
3313 if (preferredTerminal ==
"konsole")
3315 terminalCloseBool = (d->m_terminalOptionStr.contains(
"--noclose" ) > 0);
3316 w.terminalCloseCheck->setChecked(terminalCloseBool);
3317 d->m_terminalOptionStr.remove(
"--noclose");
3321 w.terminalCloseCheck->hide();
3324 w.terminalCheck->setChecked(d->m_terminalBool);
3325 w.terminalEdit->setText(d->m_terminalOptionStr);
3326 w.terminalCloseCheck->setEnabled(d->m_terminalBool);
3327 w.terminalEdit->setEnabled(d->m_terminalBool);
3328 w.terminalEditLabel->setEnabled(d->m_terminalBool);
3330 w.suidCheck->setChecked(d->m_suidBool);
3331 w.suidEdit->setText(d->m_suidUserStr);
3332 w.suidEdit->setEnabled(d->m_suidBool);
3333 w.suidEditLabel->setEnabled(d->m_suidBool);
3335 w.startupInfoCheck->setChecked(d->m_startupBool);
3336 w.systrayCheck->setChecked(d->m_systrayBool);
3338 if (d->m_dbusStartupType ==
"unique")
3339 w.dbusCombo->setCurrentIndex(2);
3340 else if (d->m_dbusStartupType ==
"multi")
3341 w.dbusCombo->setCurrentIndex(1);
3342 else if (d->m_dbusStartupType ==
"wait")
3343 w.dbusCombo->setCurrentIndex(3);
3345 w.dbusCombo->setCurrentIndex(0);
3351 int i, maxEntries = 1000;
3353 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
3354 kcom->
addItem(QString::fromLatin1(pw->pw_name));
3358 w.suidEdit->setCompletionObject(kcom,
true);
3359 w.suidEdit->setAutoDeleteCompletionObject(
true );
3367 connect( w.terminalEdit, SIGNAL(textChanged(
QString)),
3369 connect( w.terminalCloseCheck, SIGNAL(toggled(
bool)),
3371 connect( w.terminalCheck, SIGNAL(toggled(
bool)),
3373 connect( w.suidCheck, SIGNAL(toggled(
bool)),
3375 connect( w.suidEdit, SIGNAL(textChanged(
QString)),
3377 connect( w.startupInfoCheck, SIGNAL(toggled(
bool)),
3379 connect( w.systrayCheck, SIGNAL(toggled(
bool)),
3381 connect( w.dbusCombo, SIGNAL(activated(
int)),
3384 if ( dlg.exec() == QDialog::Accepted )
3386 d->m_terminalOptionStr = w.terminalEdit->text().trimmed();
3387 d->m_terminalBool = w.terminalCheck->isChecked();
3388 d->m_suidBool = w.suidCheck->isChecked();
3389 d->m_suidUserStr = w.suidEdit->text().trimmed();
3390 d->m_startupBool = w.startupInfoCheck->isChecked();
3391 d->m_systrayBool = w.systrayCheck->isChecked();
3393 if (w.terminalCloseCheck->isChecked())
3395 d->m_terminalOptionStr.append(
" --noclose");
3398 switch(w.dbusCombo->currentIndex())
3400 case 1: d->m_dbusStartupType =
"multi";
break;
3401 case 2: d->m_dbusStartupType =
"unique";
break;
3402 case 3: d->m_dbusStartupType =
"wait";
break;
3403 default: d->m_dbusStartupType =
"none";
break;
3410 if ( _items.count() != 1 ) {
3429 return config.hasApplicationType() &&
3434 #include "kpropertiesdialog.moc"
3435 #include "kpropertiesdialog_p.moc"