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) {
948 grid->addWidget(l, curRow, 0, Qt::AlignRight | Qt::AlignTop);
952 l =
new QLabel(mimeComment, box );
953 grid->addWidget(box, curRow++, 2);
956 button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
957 button->setIcon(
KIcon(QString::fromLatin1(
"configure")) );
960 button->setText(
i18n(
"Create New File Type"));
962 button->setText(
i18n(
"File Type Options"));
970 if ( !magicMimeComment.isEmpty() && magicMimeComment != mimeComment )
972 l =
new QLabel(
i18n(
"Contents:"), d->m_frame );
973 grid->addWidget(l, curRow, 0, Qt::AlignRight);
975 l =
new QLabel(magicMimeComment, d->m_frame );
976 grid->addWidget(l, curRow++, 2);
979 if ( !directory.isEmpty() )
981 l =
new QLabel(
i18n(
"Location:"), d->m_frame );
982 grid->addWidget(l, curRow, 0, Qt::AlignRight);
986 l->setLayoutDirection(Qt::LeftToRight);
989 if (
properties->layoutDirection() == Qt::RightToLeft)
990 l->setAlignment( Qt::AlignRight );
991 l->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
992 grid->addWidget(l, curRow++, 2);
996 grid->addWidget(l, curRow, 0, Qt::AlignRight);
998 d->m_sizeLabel =
new QLabel( d->m_frame );
999 grid->addWidget( d->m_sizeLabel, curRow++, 2 );
1003 d->m_sizeLabel->setText(QString::fromLatin1(
"%1 (%2)").arg(
KIO::convertSize(totalSize))
1005 d->m_sizeDetermineButton = 0L;
1006 d->m_sizeStopButton = 0L;
1010 QHBoxLayout * sizelay =
new QHBoxLayout();
1011 grid->addLayout( sizelay, curRow++, 2 );
1014 d->m_sizeDetermineButton =
new QPushButton(
i18n(
"Calculate"), d->m_frame );
1016 connect( d->m_sizeDetermineButton, SIGNAL(clicked()),
this, SLOT(
slotSizeDetermine()) );
1017 connect( d->m_sizeStopButton, SIGNAL(clicked()),
this, SLOT(
slotSizeStop()) );
1018 sizelay->addWidget(d->m_sizeDetermineButton, 0);
1019 sizelay->addWidget(d->m_sizeStopButton, 0);
1020 sizelay->addStretch(10);
1023 if ( isLocal && !hasRoot )
1025 d->m_sizeDetermineButton->setText(
i18n(
"Refresh") );
1029 d->m_sizeStopButton->setEnabled(
false );
1032 if (!d->bMultiple && item.
isLink()) {
1033 l =
new QLabel(
i18n(
"Points to:"), d->m_frame );
1034 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1037 grid->addWidget(d->m_linkTargetLineEdit, curRow++, 2);
1038 connect(d->m_linkTargetLineEdit, SIGNAL(textChanged(
QString)),
this, SLOT(
setDirty()));
1046 l =
new QLabel(
i18n(
"Created:"), d->m_frame );
1047 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1050 grid->addWidget(l, curRow++, 2);
1056 l =
new QLabel(
i18n(
"Modified:"), d->m_frame );
1057 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1060 grid->addWidget(l, curRow++, 2);
1066 l =
new QLabel(
i18n(
"Accessed:"), d->m_frame );
1067 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1070 grid->addWidget(l, curRow++, 2);
1074 if ( isLocal && hasDirs )
1079 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( mp->mountPoint() );
1080 if(info.size() != 0 )
1082 sep =
new KSeparator( Qt::Horizontal, d->m_frame);
1083 grid->addWidget(sep, curRow, 0, 1, 3);
1085 if (mp->mountPoint() !=
"/")
1087 l =
new QLabel(
i18n(
"Mounted on:"), d->m_frame );
1088 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1091 l->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
1092 grid->addWidget( l, curRow++, 2 );
1095 l =
new QLabel(
i18n(
"Device usage:"), d->m_frame );
1096 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1099 grid->addWidget( d->m_capacityBar, curRow++, 2);
1101 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
1109 bool KFilePropsPlugin::enableIconButton()
const
1111 bool iconEnabled =
false;
1129 if ( d->m_lined && !d->m_bFromTemplate )
1131 d->m_lined->setReadOnly( ro );
1144 const int pos = d->oldFileName.lastIndexOf(
'.');
1146 mime =
'*' + d->oldFileName.mid(pos);
1152 QString keditfiletype = QString::fromLatin1(
"keditfiletype");
1159 keditfiletype, keditfiletype ,
properties->window());
1162 void KFilePropsPlugin::slotIconChanged()
1164 d->bIconChanged =
true;
1168 void KFilePropsPlugin::nameFileChanged(
const QString &text )
1174 void KFilePropsPlugin::determineRelativePath(
const QString & path )
1178 if (d->m_sRelativePath.startsWith(
'/'))
1181 if (d->m_sRelativePath.startsWith(
'/'))
1182 d->m_sRelativePath.clear();
1184 d->m_sRelativePath = path;
1193 d->m_capacityBar->setText(
1194 i18nc(
"Available space out of total partition size (percent used)",
"%1 free of %2 (%3% used)",
1197 100 - (
int)(100.0 * kibAvail / kibSize) ));
1199 d->m_capacityBar->setValue(100 - (
int)(100.0 * kibAvail / kibSize));
1207 d->m_sizeLabel->setText(
1208 i18n(
"Calculating... %1 (%2)\n%3, %4",
1211 i18np(
"1 file",
"%1 files", totalFiles),
1212 i18np(
"1 sub-folder",
"%1 sub-folders", totalSubdirs)));
1224 d->m_sizeLabel->setText( QString::fromLatin1(
"%1 (%2)\n%3, %4")
1227 .arg(
i18np(
"1 file",
"%1 files",totalFiles))
1228 .arg(
i18np(
"1 sub-folder",
"%1 sub-folders",totalSubdirs)));
1230 d->m_sizeStopButton->setEnabled(
false);
1232 d->m_sizeDetermineButton->setText(
i18n(
"Refresh") );
1233 d->m_sizeDetermineButton->setEnabled(
true);
1235 delete d->dirSizeUpdateTimer;
1236 d->dirSizeUpdateTimer = 0;
1241 d->m_sizeLabel->setText(
i18n(
"Calculating...") );
1242 kDebug(250) <<
" KFilePropsPlugin::slotSizeDetermine() properties->item()=" <<
properties->
item();
1246 d->dirSizeUpdateTimer =
new QTimer(
this);
1247 connect( d->dirSizeUpdateTimer, SIGNAL(
timeout()),
1249 d->dirSizeUpdateTimer->start(500);
1250 connect( d->dirSizeJob, SIGNAL(result(
KJob*)),
1252 d->m_sizeStopButton->setEnabled(
true);
1253 d->m_sizeDetermineButton->setEnabled(
false);
1256 if ( d->m_capacityBar )
1264 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( mp->mountPoint() );
1265 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
1273 if ( d->dirSizeJob )
1276 d->m_sizeLabel->setText(
i18n(
"At least %1",
1278 d->dirSizeJob->kill();
1281 if ( d->dirSizeUpdateTimer )
1282 d->dirSizeUpdateTimer->stop();
1284 d->m_sizeStopButton->setEnabled(
false);
1285 d->m_sizeDetermineButton->setEnabled(
true);
1300 if ( d->dirSizeJob )
1303 kDebug(250) <<
"KFilePropsPlugin::applyChanges";
1305 if (qobject_cast<QLineEdit*>(d->nameArea))
1309 while ( ! n.isEmpty() && n[n.length()-1].isSpace() )
1310 n.truncate( n.length() - 1 );
1319 kDebug(250) <<
"oldname = " << d->oldName;
1320 kDebug(250) <<
"newname = " << n;
1321 if ( d->oldName != n || d->m_bFromTemplate ) {
1326 if (d->bDesktopFile && !newFileName.endsWith(QLatin1String(
".desktop")) &&
1327 !newFileName.endsWith(QLatin1String(
".kdelnk")))
1328 newFileName +=
".desktop";
1334 if ( !d->m_sRelativePath.isEmpty() )
1338 kDebug(250) <<
"old = " << oldurl.
url();
1341 if ( !d->m_bFromTemplate )
1346 connect( job, SIGNAL(result(
KJob*)),
1351 QEventLoop eventLoop;
1353 &eventLoop, SLOT(
quit()));
1354 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
1359 if ( !d->m_sRelativePath.isEmpty() )
1369 kDebug(250) <<
"KFilePropsPlugin::slotCopyFinished";
1388 if (d->bDesktopFile && !d->m_sRelativePath.isEmpty())
1390 kDebug(250) <<
"KFilePropsPlugin::slotCopyFinished " << d->m_sRelativePath;
1393 kDebug(250) <<
"KFilePropsPlugin::slotCopyFinished path=" << newURL.
path();
1397 if ( d->bKDesktopMode && d->bDesktopFile ) {
1401 if ( d->m_bFromTemplate ) {
1408 cg.writeEntry(
"Name", nameStr );
1413 if (d->m_linkTargetLineEdit && !d->bMultiple) {
1415 const QString newTarget = d->m_linkTargetLineEdit->text();
1416 if (newTarget != item.
linkDest()) {
1417 kDebug(250) <<
"Updating target of symlink to" << newTarget;
1427 if ( d->m_bFromTemplate ) {
1429 KDesktopFile templateResult ( static_cast<KIO::CopyJob*>(job)->srcUrls().first().toLocalFile() );
1437 fileItemList << appLink;
1446 void KFilePropsPlugin::applyIconChanges()
1449 if ( !iconButton || !d->bIconChanged )
1473 if ( str != iconButton->
icon() )
1474 sIcon = iconButton->
icon();
1477 kDebug(250) <<
"**" << path <<
"**";
1480 if ( !sIcon.isEmpty() || QFile::exists(path) )
1483 kDebug(250) <<
"sIcon = " << (sIcon);
1484 kDebug(250) <<
"str = " << (str);
1485 cfg.desktopGroup().writeEntry(
"Icon", sIcon );
1488 cfg.reparseConfiguration();
1489 if ( cfg.desktopGroup().readEntry(
"Icon") != sIcon ) {
1491 "have sufficient access to write to <b>%1</b>.</qt>", path));
1514 class KFilePermissionsPropsPlugin::KFilePermissionsPropsPluginPrivate
1517 KFilePermissionsPropsPluginPrivate()
1520 ~KFilePermissionsPropsPluginPrivate()
1525 QCheckBox *cbRecursive;
1526 QLabel *explanationLabel;
1527 KComboBox *ownerPermCombo, *groupPermCombo, *othersPermCombo;
1528 QCheckBox *extraCheckbox;
1529 mode_t partialPermissions;
1531 bool canChangePermissions;
1533 bool hasExtendedACL;
1536 bool fileSystemSupportsACLs;
1551 #define UniOwner (S_IRUSR|S_IWUSR|S_IXUSR)
1552 #define UniGroup (S_IRGRP|S_IWGRP|S_IXGRP)
1553 #define UniOthers (S_IROTH|S_IWOTH|S_IXOTH)
1554 #define UniRead (S_IRUSR|S_IRGRP|S_IROTH)
1555 #define UniWrite (S_IWUSR|S_IWGRP|S_IWOTH)
1556 #define UniExec (S_IXUSR|S_IXGRP|S_IXOTH)
1557 #define UniSpecial (S_ISUID|S_ISGID|S_ISVTX)
1561 const mode_t KFilePermissionsPropsPlugin::standardPermissions[4] = { 0,
UniRead,
UniRead|
UniWrite, (mode_t)-1 };
1564 const char *KFilePermissionsPropsPlugin::permissionsTexts[4][4] = {
1576 I18N_NOOP(
"Can View/Read & Modify/Write"),
1584 d->cbRecursive = 0L;
1585 d->grpCombo = 0L; d->grpEdit = 0;
1591 bool IamRoot = (geteuid() == 0);
1594 bool isLink = item.
isLink();
1595 bool isDir = item.
isDir();
1596 bool hasDir = item.
isDir();
1598 d->partialPermissions = d->permissions;
1599 d->isIrregular = isIrregular(d->permissions, isDir, isLink);
1600 d->strOwner = item.
user();
1601 d->strGroup = item.
group();
1603 d->extendedACL = item.
ACL();
1605 d->fileSystemSupportsACLs =
false;
1611 KFileItemList::const_iterator it = items.begin();
1612 const KFileItemList::const_iterator kend = items.end();
1613 for ( ++it ; it != kend; ++it )
1616 if (!d->isIrregular)
1617 d->isIrregular |= isIrregular((*it).permissions(),
1618 (*it).isDir() == isDir,
1619 (*it).isLink() == isLink);
1620 d->hasExtendedACL = d->hasExtendedACL || (*it).hasExtendedACL();
1621 if ( (*it).isLink() != isLink )
1623 if ( (*it).isDir() != isDir )
1625 hasDir |= (*it).isDir();
1626 if ( (*it).permissions() != d->permissions )
1628 d->permissions &= (*it).permissions();
1629 d->partialPermissions |= (*it).permissions();
1631 if ( (*it).user() != d->strOwner )
1632 d->strOwner.clear();
1633 if ( (*it).group() != d->strGroup )
1634 d->strGroup.clear();
1648 d->partialPermissions = d->partialPermissions & ~d->permissions;
1650 bool isMyFile =
false;
1652 if (isLocal && !d->strOwner.isEmpty()) {
1653 struct passwd *myself = getpwuid( geteuid() );
1656 isMyFile = (d->strOwner == QString::fromLocal8Bit(myself->pw_name));
1658 kWarning() <<
"I don't exist ?! geteuid=" << geteuid();
1666 d->canChangePermissions = (isMyFile || IamRoot) && (!isLink);
1671 d->m_frame =
new QFrame();
1674 QBoxLayout *box =
new QVBoxLayout( d->m_frame );
1675 box->setMargin( 0 );
1684 gb =
new QGroupBox (
i18n(
"Access Permissions"), d->m_frame );
1685 box->addWidget (gb);
1687 gl =
new QGridLayout (gb);
1688 gl->setColumnStretch(1, 1);
1690 l = d->explanationLabel =
new QLabel(
"", gb );
1692 d->explanationLabel->setText(
i18np(
"This file is a link and does not have permissions.",
1693 "All files are links and do not have permissions.",
1695 else if (!d->canChangePermissions)
1696 d->explanationLabel->setText(
i18n(
"Only the owner can change permissions."));
1697 gl->addWidget(l, 0, 0, 1, 2);
1700 gl->addWidget(lbl, 1, 0, Qt::AlignRight);
1701 l = d->ownerPermCombo =
new KComboBox(gb);
1703 gl->addWidget(l, 1, 1);
1704 connect(l, SIGNAL(activated(
int)),
this, SIGNAL(
changed()));
1705 l->setWhatsThis(
i18n(
"Specifies the actions that the owner is allowed to do."));
1708 gl->addWidget(lbl, 2, 0, Qt::AlignRight);
1709 l = d->groupPermCombo =
new KComboBox(gb);
1711 gl->addWidget(l, 2, 1);
1712 connect(l, SIGNAL(activated(
int)),
this, SIGNAL(
changed()));
1713 l->setWhatsThis(
i18n(
"Specifies the actions that the members of the group are allowed to do."));
1716 gl->addWidget(lbl, 3, 0, Qt::AlignRight);
1717 l = d->othersPermCombo =
new KComboBox(gb);
1719 gl->addWidget(l, 3, 1);
1720 connect(l, SIGNAL(activated(
int)),
this, SIGNAL(
changed()));
1721 l->setWhatsThis(
i18n(
"Specifies the actions that all users, who are neither "
1722 "owner nor in the group, are allowed to do."));
1725 l = d->extraCheckbox =
new QCheckBox(hasDir ?
1726 i18n(
"Only own&er can rename and delete folder content") :
1727 i18n(
"Is &executable"),
1729 connect( d->extraCheckbox, SIGNAL(clicked()),
this, SIGNAL(
changed()) );
1730 gl->addWidget(l, 4, 1);
1731 l->setWhatsThis(hasDir ?
i18n(
"Enable this option to allow only the folder's owner to "
1732 "delete or rename the contained files and folders. Other "
1733 "users can only add new files, which requires the 'Modify "
1734 "Content' permission.")
1735 :
i18n(
"Enable this option to mark the file as executable. This only makes "
1736 "sense for programs and scripts. It is required when you want to "
1739 QLayoutItem *spacer =
new QSpacerItem(0, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
1740 gl->addItem(spacer, 5, 0, 1, 3);
1743 gl->addWidget(pbAdvancedPerm, 6, 0, 1, 2, Qt::AlignRight);
1744 connect(pbAdvancedPerm, SIGNAL(clicked()),
this, SLOT(slotShowAdvancedPermissions()));
1747 d->extraCheckbox = 0;
1752 box->addWidget (gb);
1754 gl =
new QGridLayout (gb);
1755 gl->addItem(
new QSpacerItem(0, 10), 0, 0);
1759 gl->addWidget (l, 1, 0, Qt::AlignRight);
1766 int i, maxEntries = 1000;
1767 struct passwd *user;
1772 if (IamRoot && isLocal)
1775 KCompletion *kcom = d->usrEdit->completionObject();
1778 for (i=0; ((user = getpwent()) != 0L) && (i < maxEntries); ++i)
1779 kcom->
addItem(QString::fromLatin1(user->pw_name));
1783 d->usrEdit->setText(d->strOwner);
1784 gl->addWidget(d->usrEdit, 1, 1);
1785 connect( d->usrEdit, SIGNAL(textChanged(
QString)),
1790 l =
new QLabel(d->strOwner, gb);
1791 gl->addWidget(l, 1, 1);
1798 user = getpwuid(geteuid());
1800 strUser = user->pw_name;
1802 #ifdef HAVE_GETGROUPLIST
1806 QVarLengthArray<int> groups;
1808 QVarLengthArray<gid_t> groups;
1810 if (getgrouplist(strUser, user->pw_gid, NULL, &groupCount) < 0) {
1811 groups.resize(groupCount);
1813 getgrouplist(strUser, user->pw_gid, groups.data(), &groupCount);
1818 for (i = 0; i < groupCount; i++) {
1819 struct group *mygroup = getgrgid(groups[i]);
1821 groupList += QString::fromLocal8Bit(mygroup->gr_name);
1823 #endif // HAVE_GETGROUPLIST
1825 bool isMyGroup = groupList.contains(d->strGroup);
1831 groupList += d->strGroup;
1834 gl->addWidget (l, 2, 0, Qt::AlignRight);
1842 if (IamRoot && isLocal)
1847 d->grpEdit->setCompletionObject(kcom,
true);
1848 d->grpEdit->setAutoDeleteCompletionObject(
true );
1850 d->grpEdit->setText(d->strGroup);
1851 gl->addWidget(d->grpEdit, 2, 1);
1852 connect( d->grpEdit, SIGNAL(textChanged(
QString)),
1855 else if ((groupList.count() > 1) && isMyFile && isLocal)
1858 d->grpCombo->setObjectName(QLatin1String(
"combogrouplist"));
1859 d->grpCombo->addItems(groupList);
1860 d->grpCombo->setCurrentIndex(groupList.indexOf(d->strGroup));
1861 gl->addWidget(d->grpCombo, 2, 1);
1862 connect( d->grpCombo, SIGNAL(activated(
int)),
1867 l =
new QLabel(d->strGroup, gb);
1868 gl->addWidget(l, 2, 1);
1871 gl->setColumnStretch(2, 10);
1874 if ( hasDir && !isLink && !isTrash )
1876 d->cbRecursive =
new QCheckBox(
i18n(
"Apply changes to all subfolders and their contents"), d->m_frame );
1877 connect( d->cbRecursive, SIGNAL(clicked()),
this, SIGNAL(
changed()) );
1878 box->addWidget( d->cbRecursive );
1881 updateAccessControls();
1887 enableAccessControls(
false);
1888 if ( pbAdvancedPerm)
1889 pbAdvancedPerm->setEnabled(
false);
1892 box->addStretch (10);
1895 #ifdef HAVE_POSIX_ACL
1896 static bool fileSystemSupportsACL(
const QByteArray& path )
1898 bool fileSystemSupportsACLs =
false;
1901 fileSystemSupportsACLs = ( statfs( path.data(), &buf ) == 0 ) && ( buf.f_flags & MNT_ACLS );
1903 fileSystemSupportsACLs =
1904 getxattr( path.data(),
"system.posix_acl_access", NULL, 0 ) >= 0 || errno == ENODATA;
1906 return fileSystemSupportsACLs;
1911 void KFilePermissionsPropsPlugin::slotShowAdvancedPermissions() {
1915 dlg.setModal(
true );
1916 dlg.setCaption(
i18n(
"Advanced Permissions") );
1924 QVBoxLayout *vbox =
new QVBoxLayout(mainw);
1927 vbox->addWidget(gb);
1929 gl =
new QGridLayout (gb);
1930 gl->addItem(
new QSpacerItem(0, 10), 0, 0);
1932 QVector<QWidget*> theNotSpecials;
1935 gl->addWidget(l, 1, 0);
1936 theNotSpecials.append( l );
1942 gl->addWidget (l, 1, 1);
1943 theNotSpecials.append( l );
1946 readWhatsThis =
i18n(
"This flag allows viewing the content of the folder.");
1948 readWhatsThis =
i18n(
"The Read flag allows viewing the content of the file.");
1949 l->setWhatsThis(readWhatsThis);
1952 l =
new QLabel(
i18n(
"Write\nEntries"), gb );
1955 gl->addWidget (l, 1, 2);
1956 theNotSpecials.append( l );
1959 writeWhatsThis =
i18n(
"This flag allows adding, renaming and deleting of files. "
1960 "Note that deleting and renaming can be limited using the Sticky flag.");
1962 writeWhatsThis =
i18n(
"The Write flag allows modifying the content of the file.");
1963 l->setWhatsThis(writeWhatsThis);
1967 l =
new QLabel(
i18nc(
"Enter folder",
"Enter"), gb );
1968 execWhatsThis =
i18n(
"Enable this flag to allow entering the folder.");
1972 execWhatsThis =
i18n(
"Enable this flag to allow executing the file as a program.");
1974 l->setWhatsThis(execWhatsThis);
1975 theNotSpecials.append( l );
1977 QSize size = l->sizeHint();
1978 size.setWidth(size.width() + 15);
1979 l->setFixedSize(size);
1980 gl->addWidget (l, 1, 3);
1983 gl->addWidget(l, 1, 4, 1, 2);
1986 specialWhatsThis =
i18n(
"Special flag. Valid for the whole folder, the exact "
1987 "meaning of the flag can be seen in the right hand column.");
1989 specialWhatsThis =
i18n(
"Special flag. The exact meaning of the flag can be seen "
1990 "in the right hand column.");
1991 l->setWhatsThis(specialWhatsThis);
1994 gl->addWidget (cl[0], 2, 0);
1995 theNotSpecials.append( cl[0] );
1998 gl->addWidget (cl[1], 3, 0);
1999 theNotSpecials.append( cl[1] );
2002 gl->addWidget (cl[2], 4, 0);
2003 theNotSpecials.append( cl[2] );
2006 gl->addWidget(l, 2, 5);
2009 setUidWhatsThis =
i18n(
"If this flag is set, the owner of this folder will be "
2010 "the owner of all new files.");
2012 setUidWhatsThis =
i18n(
"If this file is an executable and the flag is set, it will "
2013 "be executed with the permissions of the owner.");
2014 l->setWhatsThis(setUidWhatsThis);
2017 gl->addWidget(l, 3, 5);
2020 setGidWhatsThis =
i18n(
"If this flag is set, the group of this folder will be "
2021 "set for all new files.");
2023 setGidWhatsThis =
i18n(
"If this file is an executable and the flag is set, it will "
2024 "be executed with the permissions of the group.");
2025 l->setWhatsThis(setGidWhatsThis);
2027 l =
new QLabel(
i18nc(
"File permission",
"Sticky"), gb);
2028 gl->addWidget(l, 4, 5);
2031 stickyWhatsThis =
i18n(
"If the Sticky flag is set on a folder, only the owner "
2032 "and root can delete or rename files. Otherwise everybody "
2033 "with write permissions can do this.");
2035 stickyWhatsThis =
i18n(
"The Sticky flag on a file is ignored on Linux, but may "
2036 "be used on some systems");
2037 l->setWhatsThis(stickyWhatsThis);
2039 mode_t aPermissions, aPartialPermissions;
2040 mode_t dummy1, dummy2;
2042 if (!d->isIrregular) {
2045 getPermissionMasks(aPartialPermissions,
2052 getPermissionMasks(dummy1,
2053 aPartialPermissions,
2059 aPartialPermissions = 0;
2064 aPermissions = d->permissions;
2065 aPartialPermissions = d->partialPermissions;
2069 QCheckBox *cba[3][4];
2070 for (
int row = 0; row < 3 ; ++row) {
2071 for (
int col = 0; col < 4; ++col) {
2072 QCheckBox *cb =
new QCheckBox(gb);
2073 if ( col != 3 ) theNotSpecials.append( cb );
2075 cb->setChecked(aPermissions & fperm[row][col]);
2076 if ( aPartialPermissions & fperm[row][col] )
2079 cb->setCheckState(Qt::PartiallyChecked);
2081 else if (d->cbRecursive && d->cbRecursive->isChecked())
2084 cb->setEnabled( d->canChangePermissions );
2085 gl->addWidget (cb, row+2, col+1);
2088 cb->setWhatsThis(readWhatsThis);
2091 cb->setWhatsThis(writeWhatsThis);
2094 cb->setWhatsThis(execWhatsThis);
2099 cb->setWhatsThis(setUidWhatsThis);
2102 cb->setWhatsThis(setGidWhatsThis);
2105 cb->setWhatsThis(stickyWhatsThis);
2112 gl->setColumnStretch(6, 10);
2114 #ifdef HAVE_POSIX_ACL
2115 KACLEditWidget *extendedACLs = 0;
2120 d->fileSystemSupportsACLs = fileSystemSupportsACL( path );
2122 if ( d->fileSystemSupportsACLs ) {
2123 std::for_each( theNotSpecials.begin(), theNotSpecials.end(), std::mem_fun( &QWidget::hide ) );
2124 extendedACLs =
new KACLEditWidget( mainw );
2125 vbox->addWidget(extendedACLs);
2126 if ( d->extendedACL.isValid() && d->extendedACL.isExtended() )
2127 extendedACLs->setACL( d->extendedACL );
2129 extendedACLs->setACL(
KACL( aPermissions ) );
2131 if ( d->defaultACL.isValid() )
2132 extendedACLs->setDefaultACL( d->defaultACL );
2135 extendedACLs->setAllowDefaults(
true );
2138 dlg.setMainWidget( mainw );
2139 if (dlg.exec() != KDialog::Accepted)
2142 mode_t andPermissions = mode_t(~0);
2143 mode_t orPermissions = 0;
2144 for (
int row = 0; row < 3; ++row)
2145 for (
int col = 0; col < 4; ++col) {
2146 switch (cba[row][col]->checkState())
2149 orPermissions |= fperm[row][col];
2152 andPermissions &= ~fperm[row][col];
2159 d->isIrregular =
false;
2161 KFileItemList::const_iterator it = items.begin();
2162 const KFileItemList::const_iterator kend = items.end();
2163 for ( ; it != kend; ++it ) {
2164 if (isIrregular(((*it).permissions() & andPermissions) | orPermissions,
2165 (*it).isDir(), (*it).isLink())) {
2166 d->isIrregular =
true;
2171 d->permissions = orPermissions;
2172 d->partialPermissions = andPermissions;
2174 #ifdef HAVE_POSIX_ACL
2176 if ( extendedACLs ) {
2177 d->extendedACL = extendedACLs->getACL();
2178 d->defaultACL = extendedACLs->getDefaultACL();
2179 d->hasExtendedACL = d->extendedACL.isExtended() || d->defaultACL.isValid();
2180 d->permissions = d->extendedACL.basePermissions();
2181 d->permissions |= ( andPermissions | orPermissions ) & ( S_ISUID|S_ISGID|S_ISVTX );
2185 updateAccessControls();
2205 void KFilePermissionsPropsPlugin::setComboContent(
QComboBox *combo, PermissionsTarget target,
2206 mode_t permissions, mode_t partial) {
2212 combo->addItem(
i18n(
"Link"));
2213 combo->setCurrentIndex(0);
2217 mode_t tMask = permissionsMasks[target];
2219 for (textIndex = 0; standardPermissions[textIndex] != (mode_t)-1; textIndex++) {
2220 if ((standardPermissions[textIndex]&tMask) == (permissions&tMask&(
UniRead|
UniWrite)))
2223 Q_ASSERT(standardPermissions[textIndex] != (mode_t)-1);
2225 for (
int i = 0; permissionsTexts[(int)d->pmode][i]; i++)
2226 combo->addItem(
i18n(permissionsTexts[(
int)d->pmode][i]));
2228 if (partial & tMask & ~
UniExec) {
2229 combo->addItem(
i18n(
"Varying (No Change)"));
2230 combo->setCurrentIndex(3);
2233 combo->setCurrentIndex(textIndex);
2238 bool KFilePermissionsPropsPlugin::isIrregular(mode_t permissions,
bool isDir,
bool isLink) {
2242 mode_t p = permissions;
2243 if (p & (S_ISUID | S_ISGID))
2250 if ((p0 != 0) && (p0 != (S_IRUSR | S_IXUSR)) && (p0 != UniOwner))
2253 if ((p0 != 0) && (p0 != (S_IRGRP | S_IXGRP)) && (p0 != UniGroup))
2256 if ((p0 != 0) && (p0 != (S_IROTH | S_IXOTH)) && (p0 != UniOthers))
2265 bool usrXPossible = !p0;
2267 if ((p0 == S_IXUSR) || (p0 == (S_IWUSR | S_IXUSR)))
2269 usrXPossible =
true;
2271 else if (p0 == S_IWUSR)
2275 bool grpXPossible = !p0;
2277 if ((p0 == S_IXGRP) || (p0 == (S_IWGRP | S_IXGRP)))
2279 grpXPossible =
true;
2281 else if (p0 == S_IWGRP)
2284 grpXPossible =
true;
2287 bool othXPossible = !p0;
2289 if ((p0 == S_IXOTH) || (p0 == (S_IWOTH | S_IXOTH)))
2291 othXPossible =
true;
2293 else if (p0 == S_IWOTH)
2297 return (p &
UniExec) && !(usrXPossible && grpXPossible && othXPossible);
2301 void KFilePermissionsPropsPlugin::enableAccessControls(
bool enable) {
2302 d->ownerPermCombo->setEnabled(enable);
2303 d->groupPermCombo->setEnabled(enable);
2304 d->othersPermCombo->setEnabled(enable);
2305 if (d->extraCheckbox)
2306 d->extraCheckbox->setEnabled(enable);
2307 if ( d->cbRecursive )
2308 d->cbRecursive->setEnabled(enable);
2312 void KFilePermissionsPropsPlugin::updateAccessControls() {
2314 d->permissions, d->partialPermissions);
2316 d->permissions, d->partialPermissions);
2318 d->permissions, d->partialPermissions);
2322 enableAccessControls(
false);
2325 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2326 if (d->canChangePermissions)
2327 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2328 i18np(
"This file uses advanced permissions",
2329 "These files use advanced permissions.",
2331 if (d->partialPermissions &
UniExec) {
2332 d->extraCheckbox->setTristate();
2333 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
2336 d->extraCheckbox->setTristate(
false);
2337 d->extraCheckbox->setChecked(d->permissions &
UniExec);
2341 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2344 if ( d->cbRecursive )
2345 d->cbRecursive->setEnabled( d->canChangePermissions && !d->isIrregular );
2347 if (d->canChangePermissions)
2348 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2349 i18np(
"This folder uses advanced permissions.",
2350 "These folders use advanced permissions.",
2352 if (d->partialPermissions & S_ISVTX) {
2353 d->extraCheckbox->setTristate();
2354 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
2357 d->extraCheckbox->setTristate(
false);
2358 d->extraCheckbox->setChecked(d->permissions & S_ISVTX);
2362 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2363 if (d->canChangePermissions)
2364 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2365 i18n(
"These files use advanced permissions.") :
"");
2367 if (d->partialPermissions & S_ISVTX) {
2368 d->extraCheckbox->setTristate();
2369 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
2372 d->extraCheckbox->setTristate(
false);
2373 d->extraCheckbox->setChecked(d->permissions & S_ISVTX);
2380 void KFilePermissionsPropsPlugin::getPermissionMasks(mode_t &andFilePermissions,
2381 mode_t &andDirPermissions,
2382 mode_t &orFilePermissions,
2383 mode_t &orDirPermissions) {
2385 andDirPermissions = mode_t(~(S_ISUID|S_ISGID));
2386 orFilePermissions = 0;
2387 orDirPermissions = 0;
2391 mode_t m = standardPermissions[d->ownerPermCombo->currentIndex()];
2392 if (m != (mode_t) -1) {
2394 if ((m & UniOwner) &&
2396 ((d->pmode ==
PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
2397 andFilePermissions &= ~(S_IRUSR | S_IWUSR);
2399 andFilePermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2400 if ((m & S_IRUSR) && (d->extraCheckbox->checkState() == Qt::Checked))
2401 orFilePermissions |= S_IXUSR;
2406 orDirPermissions |= S_IXUSR;
2407 andDirPermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2410 m = standardPermissions[d->groupPermCombo->currentIndex()];
2411 if (m != (mode_t) -1) {
2413 if ((m & UniGroup) &&
2415 ((d->pmode ==
PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
2416 andFilePermissions &= ~(S_IRGRP | S_IWGRP);
2418 andFilePermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2419 if ((m & S_IRGRP) && (d->extraCheckbox->checkState() == Qt::Checked))
2420 orFilePermissions |= S_IXGRP;
2425 orDirPermissions |= S_IXGRP;
2426 andDirPermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2429 m = d->othersPermCombo->currentIndex() >= 0 ? standardPermissions[d->othersPermCombo->currentIndex()] : (mode_t)-1;
2430 if (m != (mode_t) -1) {
2432 if ((m & UniOthers) &&
2434 ((d->pmode ==
PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
2435 andFilePermissions &= ~(S_IROTH | S_IWOTH);
2437 andFilePermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2438 if ((m & S_IROTH) && (d->extraCheckbox->checkState() == Qt::Checked))
2439 orFilePermissions |= S_IXOTH;
2444 orDirPermissions |= S_IXOTH;
2445 andDirPermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2449 (d->extraCheckbox->checkState() != Qt::PartiallyChecked)) {
2450 andDirPermissions &= ~S_ISVTX;
2451 if (d->extraCheckbox->checkState() == Qt::Checked)
2452 orDirPermissions |= S_ISVTX;
2458 mode_t orFilePermissions;
2459 mode_t orDirPermissions;
2460 mode_t andFilePermissions;
2461 mode_t andDirPermissions;
2463 if (!d->canChangePermissions)
2466 if (!d->isIrregular)
2467 getPermissionMasks(andFilePermissions,
2472 orFilePermissions = d->permissions;
2473 andFilePermissions = d->partialPermissions;
2474 orDirPermissions = d->permissions;
2475 andDirPermissions = d->partialPermissions;
2480 owner = d->usrEdit->text();
2482 group = d->grpEdit->text();
2483 else if (d->grpCombo)
2484 group = d->grpCombo->currentText();
2486 if (owner == d->strOwner)
2489 if (group == d->strGroup)
2492 bool recursive = d->cbRecursive && d->cbRecursive->isChecked();
2493 bool permissionChange =
false;
2497 KFileItemList::const_iterator it = items.begin();
2498 const KFileItemList::const_iterator kend = items.end();
2499 for ( ; it != kend; ++it ) {
2500 if ((*it).isDir()) {
2502 if ((*it).permissions() != (((*it).permissions() & andDirPermissions) | orDirPermissions))
2503 permissionChange =
true;
2505 else if ((*it).isFile()) {
2507 if ((*it).permissions() != (((*it).permissions() & andFilePermissions) | orFilePermissions))
2508 permissionChange =
true;
2515 if (owner.isEmpty() && group.isEmpty() && !recursive
2516 && !permissionChange && !ACLChange && !defaultACLChange)
2520 if (files.count() > 0) {
2521 job =
KIO::chmod( files, orFilePermissions, ~andFilePermissions,
2522 owner, group,
false );
2523 if ( ACLChange && d->fileSystemSupportsACLs )
2524 job->
addMetaData(
"ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():
"ACL_DELETE" );
2525 if ( defaultACLChange && d->fileSystemSupportsACLs )
2526 job->
addMetaData(
"DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():
"ACL_DELETE" );
2528 connect( job, SIGNAL(result(
KJob*)),
2529 SLOT(slotChmodResult(
KJob*)) );
2530 QEventLoop eventLoop;
2532 &eventLoop, SLOT(
quit()));
2533 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
2535 if (dirs.count() > 0) {
2536 job =
KIO::chmod( dirs, orDirPermissions, ~andDirPermissions,
2537 owner, group, recursive );
2538 if ( ACLChange && d->fileSystemSupportsACLs )
2539 job->
addMetaData(
"ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():
"ACL_DELETE" );
2540 if ( defaultACLChange && d->fileSystemSupportsACLs )
2541 job->
addMetaData(
"DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():
"ACL_DELETE" );
2543 connect( job, SIGNAL(result(
KJob*)),
2544 SLOT(slotChmodResult(
KJob*)) );
2545 QEventLoop eventLoop;
2547 &eventLoop, SLOT(
quit()));
2548 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
2552 void KFilePermissionsPropsPlugin::slotChmodResult(
KJob * job )
2554 kDebug(250) <<
"KFilePermissionsPropsPlugin::slotChmodResult";
2564 class KUrlPropsPlugin::KUrlPropsPluginPrivate
2567 KUrlPropsPluginPrivate()
2570 ~KUrlPropsPluginPrivate()
2582 d->m_frame =
new QFrame();
2584 QVBoxLayout *layout =
new QVBoxLayout(d->m_frame);
2585 layout->setMargin(0);
2588 l =
new QLabel( d->m_frame );
2589 l->setObjectName( QLatin1String(
"Label_1" ) );
2590 l->setText(
i18n(
"URL:") );
2591 layout->addWidget(l, Qt::AlignRight);
2594 layout->addWidget(d->URLEdit);
2601 if ( !f.open( QIODevice::ReadOnly ) ) {
2610 if (!d->URLStr.isEmpty()) {
2611 d->URLEdit->setUrl(
KUrl(d->URLStr) );
2615 connect( d->URLEdit, SIGNAL(textChanged(
QString)),
2618 layout->addStretch (1);
2633 if ( _items.count() != 1 )
2648 return config.hasLinkType();
2661 if ( !f.open( QIODevice::ReadWrite ) ) {
2663 "sufficient access to write to <b>%1</b>.</qt>", path));
2670 dg.
writeEntry(
"Type", QString::fromLatin1(
"Link"));
2690 class KDevicePropsPlugin::KDevicePropsPluginPrivate
2693 KDevicePropsPluginPrivate()
2696 ~KDevicePropsPluginPrivate()
2700 bool isMounted()
const {
2701 const QString dev = device->currentText();
2708 QLabel *m_freeSpaceLabel;
2709 QProgressBar *m_freeSpaceBar;
2713 QCheckBox* readonly;
2720 d->m_frame =
new QFrame();
2726 for(KMountPoint::List::ConstIterator it = mountPoints.begin();
2727 it != mountPoints.end(); ++it)
2730 QString mountPoint = mp->mountPoint();
2731 QString device = mp->mountedFrom();
2732 kDebug()<<
"mountPoint :"<<mountPoint<<
" device :"<<device<<
" mp->mountType() :"<<mp->mountType();
2734 if ((mountPoint !=
"-") && (mountPoint !=
"none") && !mountPoint.isEmpty()
2735 && device !=
"none")
2737 devices.append( device + QString::fromLatin1(
" (")
2738 + mountPoint + QString::fromLatin1(
")") );
2739 d->m_devicelist.append(device);
2740 d->mountpointlist.append(mountPoint);
2744 QGridLayout *layout =
new QGridLayout( d->m_frame );
2746 layout->setMargin(0);
2747 layout->setColumnStretch(1, 1);
2750 label =
new QLabel( d->m_frame );
2751 label->setText( devices.count() == 0 ?
2752 i18n(
"Device (/dev/fd0):") :
2754 layout->addWidget(label, 0, 0, Qt::AlignRight);
2756 d->device =
new KComboBox( d->m_frame );
2757 d->device->setObjectName( QLatin1String(
"ComboBox_device" ) );
2758 d->device->setEditable(
true );
2759 d->device->addItems( devices );
2760 layout->addWidget(d->device, 0, 1);
2761 connect( d->device, SIGNAL(activated(
int)),
2762 this, SLOT(slotActivated(
int)) );
2764 d->readonly =
new QCheckBox( d->m_frame );
2765 d->readonly->setObjectName( QLatin1String(
"CheckBox_readonly" ) );
2766 d->readonly->setText(
i18n(
"Read only") );
2767 layout->addWidget(d->readonly, 1, 1);
2769 label =
new QLabel( d->m_frame );
2770 label->setText(
i18n(
"File system:") );
2771 layout->addWidget(label, 2, 0, Qt::AlignRight);
2774 layout->addWidget(fileSystem, 2, 1);
2776 label =
new QLabel( d->m_frame );
2777 label->setText( devices.count()==0 ?
2778 i18n(
"Mount point (/mnt/floppy):") :
2779 i18n(
"Mount point:"));
2780 layout->addWidget(label, 3, 0, Qt::AlignRight);
2782 d->mountpoint =
new QLabel( d->m_frame );
2783 d->mountpoint->setObjectName( QLatin1String(
"LineEdit_mountpoint" ) );
2785 layout->addWidget(d->mountpoint, 3, 1);
2788 d->m_freeSpaceText =
new QLabel(
i18n(
"Device usage:"), d->m_frame );
2789 layout->addWidget(d->m_freeSpaceText, 4, 0, Qt::AlignRight);
2791 d->m_freeSpaceLabel =
new QLabel( d->m_frame );
2792 layout->addWidget( d->m_freeSpaceLabel, 4, 1 );
2794 d->m_freeSpaceBar =
new QProgressBar( d->m_frame );
2795 d->m_freeSpaceBar->setObjectName(
"freeSpaceBar" );
2796 layout->addWidget(d->m_freeSpaceBar, 5, 0, 1, 2);
2799 d->m_freeSpaceText->hide();
2800 d->m_freeSpaceLabel->hide();
2801 d->m_freeSpaceBar->hide();
2804 layout->addWidget(sep, 6, 0, 1, 2);
2806 layout->setRowStretch(7, 1);
2815 if ( !f.open( QIODevice::ReadOnly ) )
2823 bool ro = config.
readEntry(
"ReadOnly",
false );
2825 fileSystem->setText(config.
readEntry(
"FSType"));
2827 d->device->setEditText( deviceStr );
2828 if ( !deviceStr.isEmpty() ) {
2830 int index = d->m_devicelist.indexOf(deviceStr);
2834 slotActivated( index );
2838 if ( !mountPointStr.isEmpty() )
2840 d->mountpoint->setText( mountPointStr );
2844 d->readonly->setChecked( ro );
2846 connect( d->device, SIGNAL(activated(
int)),
2848 connect( d->device, SIGNAL(textChanged(
QString)),
2850 connect( d->readonly, SIGNAL(toggled(
bool)),
2853 connect( d->device, SIGNAL(textChanged(
QString)),
2854 this, SLOT(slotDeviceChanged()) );
2867 void KDevicePropsPlugin::updateInfo()
2870 d->m_freeSpaceText->hide();
2871 d->m_freeSpaceLabel->hide();
2872 d->m_freeSpaceBar->hide();
2874 if (!d->mountpoint->text().isEmpty() && d->isMounted()) {
2875 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( d->mountpoint->text() );
2876 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
2880 void KDevicePropsPlugin::slotActivated(
int index )
2884 if (index < d->m_devicelist.count()) {
2886 d->device->setEditText(d->m_devicelist[index]);
2887 d->mountpoint->setText(d->mountpointlist[index]);
2893 void KDevicePropsPlugin::slotDeviceChanged()
2896 int index = d->m_devicelist.indexOf( d->device->currentText() );
2898 d->mountpoint->setText( d->mountpointlist[index] );
2900 d->mountpoint->setText(
QString() );
2905 void KDevicePropsPlugin::slotFoundMountPoint(
const QString&,
2910 d->m_freeSpaceText->show();
2911 d->m_freeSpaceLabel->show();
2913 const int percUsed = kibSize != 0 ? (100 - (int)(100.0 * kibAvail / kibSize)) : 100;
2915 d->m_freeSpaceLabel->setText(
2916 i18nc(
"Available space out of total partition size (percent used)",
"%1 free of %2 (%3% used)",
2921 d->m_freeSpaceBar->setRange(0, 100);
2922 d->m_freeSpaceBar->setValue(percUsed);
2923 d->m_freeSpaceBar->show();
2928 if ( _items.count() != 1 )
2943 return config.hasDeviceType();
2954 if ( !f.open( QIODevice::ReadWrite ) )
2957 "access to write to <b>%1</b>.</qt>", path));
2964 config.
writeEntry(
"Type", QString::fromLatin1(
"FSDevice") );
2966 config.
writeEntry(
"Dev", d->device->currentText() );
2967 config.
writeEntry(
"MountPoint", d->mountpoint->text() );
2969 config.
writeEntry(
"ReadOnly", d->readonly->isChecked() );
2981 class KDesktopPropsPlugin::KDesktopPropsPluginPrivate
2984 KDesktopPropsPluginPrivate()
2985 : w( new Ui_KPropertiesDesktopBase )
2986 , m_frame( new
QFrame() )
2989 ~KDesktopPropsPluginPrivate()
2993 Ui_KPropertiesDesktopBase* w;
3002 bool m_terminalBool;
3011 d->w->setupUi(d->m_frame);
3021 d->w->nameEdit->hide();
3022 d->w->nameLabel->hide();
3026 d->w->pathEdit->lineEdit()->setAcceptDrops(
false);
3028 connect( d->w->nameEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3029 connect( d->w->genNameEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3030 connect( d->w->commentEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3031 connect( d->w->commandEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3032 connect( d->w->pathEdit, SIGNAL(textChanged(
QString)),
this, SIGNAL(
changed()) );
3034 connect( d->w->browseButton, SIGNAL(clicked()),
this, SLOT(
slotBrowseExec()) );
3035 connect( d->w->addFiletypeButton, SIGNAL(clicked()),
this, SLOT(
slotAddFiletype()) );
3036 connect( d->w->delFiletypeButton, SIGNAL(clicked()),
this, SLOT(
slotDelFiletype()) );
3037 connect( d->w->advancedButton, SIGNAL(clicked()),
this, SLOT(
slotAdvanced()) );
3048 QFile
f( d->m_origDesktopFile );
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();
3218 QScopedPointer<KDesktopFile> _config (origConfig.
copyTo(path));
3220 config.writeEntry(
"Type", QString::fromLatin1(
"Application"));
3221 config.writeEntry(
"Comment", d->w->commentEdit->text() );
3223 config.writeEntry(
"GenericName", d->w->genNameEdit->text() );
3226 if (d->m_systrayBool)
3227 config.writeEntry(
"Exec", d->w->commandEdit->text().prepend(
"ksystraycmd ") );
3229 config.writeEntry(
"Exec", d->w->commandEdit->text() );
3230 config.writeEntry(
"Path", d->w->pathEdit->lineEdit()->text() );
3234 int count = d->w->filetypeList->topLevelItemCount();
3235 for (
int i = 0; i < count; ++i) {
3236 QTreeWidgetItem *item = d->w->filetypeList->topLevelItem(i);
3237 QString preference = item->text(2);
3238 mimeTypes.append(item->text(0));
3239 if (!preference.isEmpty())
3240 mimeTypes.append(preference);
3244 config.writeXdgListEntry(
"MimeType", mimeTypes );
3246 if ( !d->w->nameEdit->isHidden() ) {
3247 QString nameStr = d->w->nameEdit->text();
3248 config.writeEntry(
"Name", nameStr );
3252 config.writeEntry(
"Terminal", d->m_terminalBool);
3253 config.writeEntry(
"TerminalOptions", d->m_terminalOptionStr);
3254 config.writeEntry(
"X-KDE-SubstituteUID", d->m_suidBool);
3255 config.writeEntry(
"X-KDE-Username", d->m_suidUserStr);
3256 config.writeEntry(
"StartupNotify", d->m_startupBool);
3257 config.writeEntry(
"X-DBUS-StartupType", d->m_dbusStartupType);
3258 config.writeEntry(
"X-DBUS-ServiceName", d->m_dbusServiceName);
3263 bool updateNeeded = !sycocaPath.startsWith(
'/');
3267 updateNeeded = !sycocaPath.startsWith(
'/');
3288 d->w->commandEdit->setText( path );
3294 dlg.setObjectName(
"KPropertiesDesktopAdv" );
3295 dlg.setModal(
true );
3299 Ui_KPropertiesDesktopAdvBase w;
3304 checkCommandChanged();
3310 QString::fromLatin1(
"konsole"));
3312 bool terminalCloseBool =
false;
3314 if (preferredTerminal ==
"konsole")
3316 terminalCloseBool = (d->m_terminalOptionStr.contains(
"--noclose" ) > 0);
3317 w.terminalCloseCheck->setChecked(terminalCloseBool);
3318 d->m_terminalOptionStr.remove(
"--noclose");
3322 w.terminalCloseCheck->hide();
3325 w.terminalCheck->setChecked(d->m_terminalBool);
3326 w.terminalEdit->setText(d->m_terminalOptionStr);
3327 w.terminalCloseCheck->setEnabled(d->m_terminalBool);
3328 w.terminalEdit->setEnabled(d->m_terminalBool);
3329 w.terminalEditLabel->setEnabled(d->m_terminalBool);
3331 w.suidCheck->setChecked(d->m_suidBool);
3332 w.suidEdit->setText(d->m_suidUserStr);
3333 w.suidEdit->setEnabled(d->m_suidBool);
3334 w.suidEditLabel->setEnabled(d->m_suidBool);
3336 w.startupInfoCheck->setChecked(d->m_startupBool);
3337 w.systrayCheck->setChecked(d->m_systrayBool);
3339 if (d->m_dbusStartupType ==
"unique")
3340 w.dbusCombo->setCurrentIndex(2);
3341 else if (d->m_dbusStartupType ==
"multi")
3342 w.dbusCombo->setCurrentIndex(1);
3343 else if (d->m_dbusStartupType ==
"wait")
3344 w.dbusCombo->setCurrentIndex(3);
3346 w.dbusCombo->setCurrentIndex(0);
3352 int i, maxEntries = 1000;
3354 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
3355 kcom->
addItem(QString::fromLatin1(pw->pw_name));
3359 w.suidEdit->setCompletionObject(kcom,
true);
3360 w.suidEdit->setAutoDeleteCompletionObject(
true );
3368 connect( w.terminalEdit, SIGNAL(textChanged(
QString)),
3370 connect( w.terminalCloseCheck, SIGNAL(toggled(
bool)),
3372 connect( w.terminalCheck, SIGNAL(toggled(
bool)),
3374 connect( w.suidCheck, SIGNAL(toggled(
bool)),
3376 connect( w.suidEdit, SIGNAL(textChanged(
QString)),
3378 connect( w.startupInfoCheck, SIGNAL(toggled(
bool)),
3380 connect( w.systrayCheck, SIGNAL(toggled(
bool)),
3382 connect( w.dbusCombo, SIGNAL(activated(
int)),
3385 if ( dlg.exec() == QDialog::Accepted )
3387 d->m_terminalOptionStr = w.terminalEdit->text().trimmed();
3388 d->m_terminalBool = w.terminalCheck->isChecked();
3389 d->m_suidBool = w.suidCheck->isChecked();
3390 d->m_suidUserStr = w.suidEdit->text().trimmed();
3391 d->m_startupBool = w.startupInfoCheck->isChecked();
3392 d->m_systrayBool = w.systrayCheck->isChecked();
3394 if (w.terminalCloseCheck->isChecked())
3396 d->m_terminalOptionStr.append(
" --noclose");
3399 switch(w.dbusCombo->currentIndex())
3401 case 1: d->m_dbusStartupType =
"multi";
break;
3402 case 2: d->m_dbusStartupType =
"unique";
break;
3403 case 3: d->m_dbusStartupType =
"wait";
break;
3404 default: d->m_dbusStartupType =
"none";
break;
3411 if ( _items.count() != 1 ) {
3430 return config.hasApplicationType() &&
3435 #include "kpropertiesdialog.moc"
3436 #include "kpropertiesdialog_p.moc"