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>
128 #include "ui_kpropertiesdesktopbase.h"
129 #include "ui_kpropertiesdesktopadvbase.h"
130 #ifdef HAVE_POSIX_ACL
140 # warning TODO: port completely to win32
148 if ( nameStr.endsWith(QLatin1String(
".desktop")) )
149 nameStr.truncate( nameStr.length() - 8 );
150 if ( nameStr.endsWith(QLatin1String(
".kdelnk")) )
151 nameStr.truncate( nameStr.length() - 7 );
157 mode_t KFilePermissionsPropsPlugin::fperm[3][4] = {
158 {S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID},
159 {S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID},
160 {S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX}
163 class KPropertiesDialog::KPropertiesDialogPrivate
172 ~KPropertiesDialogPrivate()
199 QString m_defaultName;
209 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
214 d->m_items.append(
item);
217 Q_ASSERT(!d->m_singleUrl.isEmpty());
224 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
233 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
235 if ( _items.count() > 1 )
236 setCaption(
i18np(
"Properties for 1 item",
"Properties for %1 Selected Items", _items.count() ) );
240 Q_ASSERT( !_items.isEmpty() );
241 d->m_singleUrl = _items.first().url();
242 Q_ASSERT(!d->m_singleUrl.isEmpty());
251 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
255 d->m_singleUrl = _url;
260 d->m_items.append(
KFileItem(entry, _url));
265 const QString& _defaultName,
267 :
KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
271 d->m_singleUrl = _tempUrl;
272 d->m_defaultName = _defaultName;
273 d->m_currentDir = _currentDir;
274 Q_ASSERT(!d->m_singleUrl.isEmpty());
288 if (!localPath.isEmpty())
321 if (_items.count()==1) {
338 void KPropertiesDialog::KPropertiesDialogPrivate::init()
344 connect(q, SIGNAL(okClicked()), q, SLOT(slotOk()));
345 connect(q, SIGNAL(cancelClicked()), q, SLOT(slotCancel()));
350 q->restoreDialogSize(group);
355 if (d->fileSharePage) {
362 d->fileSharePage = page;
379 qDeleteAll(d->m_pageList);
388 connect (plugin, SIGNAL (changed()),
389 plugin, SLOT (setDirty()));
391 d->m_pageList.append(plugin);
396 return d->m_singleUrl;
401 return d->m_items.first();
411 return d->m_currentDir;
416 return d->m_defaultName;
422 return KFilePropsPlugin::supports( _items ) ||
423 KFilePermissionsPropsPlugin::supports( _items ) ||
424 KDesktopPropsPlugin::supports( _items ) ||
425 KUrlPropsPlugin::supports( _items ) ||
426 KDevicePropsPlugin::supports( _items ) ||
433 d->m_aborted =
false;
435 KFilePropsPlugin * filePropsPlugin = qobject_cast<KFilePropsPlugin*>(d->m_pageList.first());
440 for (pageListIt = d->m_pageList.constBegin(); pageListIt != d->m_pageList.constEnd(); ++pageListIt) {
441 if ( (*pageListIt)->isDirty() && filePropsPlugin )
452 for (pageListIt = d->m_pageList.constBegin(); pageListIt != d->m_pageList.constEnd() && !d->m_aborted; ++pageListIt) {
453 if ( (*pageListIt)->isDirty() )
455 kDebug( 250 ) <<
"applying changes for " << (*pageListIt)->metaObject()->className();
456 (*pageListIt)->applyChanges();
460 kDebug( 250 ) <<
"skipping page " << (*pageListIt)->metaObject()->className();
464 if ( !d->m_aborted && filePropsPlugin )
485 void KPropertiesDialog::KPropertiesDialogPrivate::insertPages()
487 if (m_items.isEmpty())
490 if ( KFilePropsPlugin::supports( m_items ) ) {
495 if ( KFilePermissionsPropsPlugin::supports( m_items ) ) {
500 if ( KDesktopPropsPlugin::supports( m_items ) ) {
505 if ( KUrlPropsPlugin::supports( m_items ) ) {
510 if ( KDevicePropsPlugin::supports( m_items ) ) {
522 if ( m_items.count() != 1 )
531 QString query = QString::fromLatin1(
532 "((not exist [X-KDE-Protocol]) or "
533 " ([X-KDE-Protocol] == '%1' ) )"
536 kDebug( 250 ) <<
"trader query: " << query;
542 plugin->setObjectName(ptr->name());
544 q->insertPlugin(plugin);
550 Q_ASSERT(d->m_items.count() == 1);
551 kDebug(250) <<
"KPropertiesDialog::updateUrl (pre)" << _newUrl.
url();
552 KUrl newUrl = _newUrl;
553 emit
saveAs(d->m_singleUrl, newUrl);
554 kDebug(250) <<
"KPropertiesDialog::updateUrl (post)" << newUrl.
url();
556 d->m_singleUrl = newUrl;
557 d->m_items.first().setUrl(newUrl);
558 Q_ASSERT(!d->m_singleUrl.isEmpty());
562 if ( qobject_cast<KUrlPropsPlugin*>(it) ||
563 qobject_cast<KDesktopPropsPlugin*>(it) )
574 Q_ASSERT(d->m_items.count() == 1);
575 kDebug(250) <<
"KPropertiesDialog::rename " << _name;
578 if (!d->m_currentDir.isEmpty()) {
579 newUrl = d->m_currentDir;
582 QString tmpurl = d->m_singleUrl.url();
583 if (!tmpurl.isEmpty() && tmpurl.at(tmpurl.length() - 1) ==
'/') {
585 tmpurl.truncate(tmpurl.length() - 1);
599 class KPropertiesDialogPlugin::KPropertiesDialogPluginPrivate
602 KPropertiesDialogPluginPrivate()
605 ~KPropertiesDialogPluginPrivate()
614 :
QObject( _props ),d(new KPropertiesDialogPluginPrivate)
617 d->fontHeight = 2*
properties->fontMetrics().height();
626 #ifndef KDE_NO_DEPRECATED
650 kWarning(250) <<
"applyChanges() not implemented in page !";
655 return d->fontHeight;
660 class KFilePropsPlugin::KFilePropsPluginPrivate
663 KFilePropsPluginPrivate()
666 dirSizeUpdateTimer = 0L;
669 m_linkTargetLineEdit = 0;
671 ~KFilePropsPluginPrivate()
678 QTimer *dirSizeUpdateTimer;
697 QString m_sRelativePath;
698 bool m_bFromTemplate;
710 d->bIconChanged =
false;
712 kDebug(250) <<
"KFilePropsPlugin::KFilePropsPlugin bMultiple=" << d->bMultiple;
721 mode_t mode = item.
mode();
723 bool hasRoot = url.
path() == QLatin1String(
"/");
727 d->bKDesktopMode = protocol == QLatin1String(
"desktop") ||
732 QString magicMimeComment;
736 magicMimeComment = magicMimeType->comment();
739 if ( isReallyLocal ) {
740 directory = QDir::toNativeSeparators( directory.mid( 1 ) );
746 bool isTrash =
false;
747 d->m_bFromTemplate =
false;
750 uint iDirCount = hasDirs ? 1 : 0;
751 uint iFileCount = 1-iDirCount;
753 d->m_frame =
new QFrame();
756 QVBoxLayout *vbl =
new QVBoxLayout( d->m_frame );
758 vbl->setObjectName( QLatin1String(
"vbl" ) );
759 QGridLayout *grid =
new QGridLayout();
760 grid->setColumnStretch(0, 0);
761 grid->setColumnStretch(1, 0);
762 grid->setColumnStretch(2, 1);
764 vbl->addLayout(grid);
770 if ( !d->m_bFromTemplate ) {
782 if (d->bDesktopFile) {
783 determineRelativePath( path );
788 if ( filename.isEmpty() ) {
789 const QFileInfo finfo (item.
name());
790 filename = finfo.fileName();
792 d->m_bFromTemplate =
true;
795 d->oldFileName = filename;
800 if ( d->bKDesktopMode && d->bDesktopFile ) {
802 if (
config.desktopGroup().hasKey(
"Name" ) ) {
803 filename =
config.readName();
807 d->oldName = filename;
813 KFileItemList::const_iterator kit = items.begin();
814 const KFileItemList::const_iterator kend = items.end();
815 for ( ++kit ; kit != kend; ++kit )
818 kDebug(250) <<
"KFilePropsPlugin::KFilePropsPlugin " << url.
prettyUrl();
823 if ( bDesktopFile && (*kit).isDesktopFile() != bDesktopFile )
824 bDesktopFile =
false;
825 if ( (*kit).mode() != mode )
828 iconStr =
"document-multiple";
833 if ( !mimeComment.isNull() && (*kit).mimeComment() != mimeComment )
835 if ( isLocal && !magicMimeComment.isNull() ) {
837 if ( magicMimeType->comment() != magicMimeComment )
838 magicMimeComment.clear();
841 if ( isLocal && url.
path() == QLatin1String(
"/") )
843 if ( (*kit).isDir() && !(*kit).isLink() )
851 totalSize += (*kit).size();
856 if (!isReallyLocal && !protocol.isEmpty())
860 directory += protocol;
864 if (!isTrash && (bDesktopFile || S_ISDIR(mode))
866 && enableIconButton())
869 int bsize = 66 + 2 * iconButton->style()->pixelMetric(QStyle::PM_ButtonMargin);
870 iconButton->setFixedSize(bsize, bsize);
874 if (bDesktopFile && isLocal) {
877 iconStr =
group.readEntry(
"Icon" );
878 if (
config.hasDeviceType() )
886 d->iconArea = iconButton;
887 connect(iconButton, SIGNAL(iconChanged(QString)),
888 this, SLOT(slotIconChanged()));
891 int bsize = 66 + 2 * iconLabel->style()->pixelMetric(QStyle::PM_ButtonMargin);
892 iconLabel->setFixedSize(bsize, bsize);
894 d->iconArea = iconLabel;
896 grid->addWidget(d->iconArea, curRow, 0, Qt::AlignLeft);
898 if (d->bMultiple || isTrash || hasRoot)
904 lab->setText( filename );
908 d->m_lined =
new KLineEdit( d->m_frame );
909 d->m_lined->setText(filename);
910 d->nameArea = d->m_lined;
911 d->m_lined->setFocus();
919 if ( !extension.isEmpty() )
920 d->m_lined->setSelection( 0, filename.length() - extension.length() - 1 );
923 int lastDot = filename.lastIndexOf(
'.');
925 d->m_lined->setSelection(0, lastDot);
928 connect( d->m_lined, SIGNAL(textChanged(QString)),
929 this, SLOT(nameFileChanged(QString)) );
932 grid->addWidget(d->nameArea, curRow++, 2);
935 grid->addWidget(sep, curRow, 0, 1, 3);
939 if (!mimeComment.isEmpty() && !isTrash) {
941 grid->addWidget(l, curRow, 0, Qt::AlignRight | Qt::AlignTop);
945 l =
new QLabel(mimeComment, box );
946 grid->addWidget(box, curRow++, 2);
949 button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
950 button->setIcon(
KIcon(QString::fromLatin1(
"configure")) );
953 button->setText(
i18n(
"Create New File Type"));
955 button->setText(
i18n(
"File Type Options"));
963 if ( !magicMimeComment.isEmpty() && magicMimeComment != mimeComment )
965 l =
new QLabel(
i18n(
"Contents:"), d->m_frame );
966 grid->addWidget(l, curRow, 0, Qt::AlignRight);
968 l =
new QLabel(magicMimeComment, d->m_frame );
969 grid->addWidget(l, curRow++, 2);
972 if ( !directory.isEmpty() )
974 l =
new QLabel(
i18n(
"Location:"), d->m_frame );
975 grid->addWidget(l, curRow, 0, Qt::AlignRight);
979 l->setLayoutDirection(Qt::LeftToRight);
982 if (
properties->layoutDirection() == Qt::RightToLeft)
983 l->setAlignment( Qt::AlignRight );
984 l->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
985 grid->addWidget(l, curRow++, 2);
989 grid->addWidget(l, curRow, 0, Qt::AlignRight);
991 d->m_sizeLabel =
new QLabel( d->m_frame );
992 grid->addWidget( d->m_sizeLabel, curRow++, 2 );
996 d->m_sizeLabel->setText(QString::fromLatin1(
"%1 (%2)").arg(
KIO::convertSize(totalSize))
998 d->m_sizeDetermineButton = 0L;
999 d->m_sizeStopButton = 0L;
1003 QHBoxLayout * sizelay =
new QHBoxLayout();
1004 grid->addLayout( sizelay, curRow++, 2 );
1007 d->m_sizeDetermineButton =
new QPushButton(
i18n(
"Calculate"), d->m_frame );
1009 connect( d->m_sizeDetermineButton, SIGNAL(clicked()),
this, SLOT(
slotSizeDetermine()) );
1010 connect( d->m_sizeStopButton, SIGNAL(clicked()),
this, SLOT(
slotSizeStop()) );
1011 sizelay->addWidget(d->m_sizeDetermineButton, 0);
1012 sizelay->addWidget(d->m_sizeStopButton, 0);
1013 sizelay->addStretch(10);
1016 if ( isLocal && !hasRoot )
1018 d->m_sizeDetermineButton->setText(
i18n(
"Refresh") );
1022 d->m_sizeStopButton->setEnabled(
false );
1025 if (!d->bMultiple && item.
isLink()) {
1026 l =
new QLabel(
i18n(
"Points to:"), d->m_frame );
1027 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1030 grid->addWidget(d->m_linkTargetLineEdit, curRow++, 2);
1031 connect(d->m_linkTargetLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(
setDirty()));
1039 l =
new QLabel(
i18n(
"Created:"), d->m_frame );
1040 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1043 grid->addWidget(l, curRow++, 2);
1049 l =
new QLabel(
i18n(
"Modified:"), d->m_frame );
1050 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1053 grid->addWidget(l, curRow++, 2);
1059 l =
new QLabel(
i18n(
"Accessed:"), d->m_frame );
1060 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1063 grid->addWidget(l, curRow++, 2);
1067 if ( isLocal && hasDirs )
1073 if(info.size() != 0 )
1075 sep =
new KSeparator( Qt::Horizontal, d->m_frame);
1076 grid->addWidget(sep, curRow, 0, 1, 3);
1078 if (mp->mountPoint() !=
"/")
1080 l =
new QLabel(
i18n(
"Mounted on:"), d->m_frame );
1081 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1084 l->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
1085 grid->addWidget( l, curRow++, 2 );
1088 l =
new QLabel(
i18n(
"Device usage:"), d->m_frame );
1089 grid->addWidget(l, curRow, 0, Qt::AlignRight);
1092 grid->addWidget( d->m_capacityBar, curRow++, 2);
1094 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
1102 bool KFilePropsPlugin::enableIconButton()
const
1104 bool iconEnabled =
false;
1122 if ( d->m_lined && !d->m_bFromTemplate )
1124 d->m_lined->setReadOnly( ro );
1137 const int pos = d->oldFileName.lastIndexOf(
'.');
1139 mime =
'*' + d->oldFileName.mid(pos);
1145 QString keditfiletype = QString::fromLatin1(
"keditfiletype");
1152 keditfiletype, keditfiletype ,
properties->window());
1155 void KFilePropsPlugin::slotIconChanged()
1157 d->bIconChanged =
true;
1161 void KFilePropsPlugin::nameFileChanged(
const QString &text )
1167 void KFilePropsPlugin::determineRelativePath(
const QString & path )
1171 if (d->m_sRelativePath.startsWith(
'/'))
1174 if (d->m_sRelativePath.startsWith(
'/'))
1175 d->m_sRelativePath.clear();
1177 d->m_sRelativePath = path;
1186 d->m_capacityBar->setText(
1187 i18nc(
"Available space out of total partition size (percent used)",
"%1 free of %2 (%3% used)",
1190 100 - (
int)(100.0 * kibAvail / kibSize) ));
1192 d->m_capacityBar->setValue(100 - (
int)(100.0 * kibAvail / kibSize));
1200 d->m_sizeLabel->setText(
1201 i18n(
"Calculating... %1 (%2)\n%3, %4",
1204 i18np(
"1 file",
"%1 files", totalFiles),
1205 i18np(
"1 sub-folder",
"%1 sub-folders", totalSubdirs)));
1217 d->m_sizeLabel->setText( QString::fromLatin1(
"%1 (%2)\n%3, %4")
1220 .arg(
i18np(
"1 file",
"%1 files",totalFiles))
1221 .arg(
i18np(
"1 sub-folder",
"%1 sub-folders",totalSubdirs)));
1223 d->m_sizeStopButton->setEnabled(
false);
1225 d->m_sizeDetermineButton->setText(
i18n(
"Refresh") );
1226 d->m_sizeDetermineButton->setEnabled(
true);
1228 delete d->dirSizeUpdateTimer;
1229 d->dirSizeUpdateTimer = 0;
1234 d->m_sizeLabel->setText(
i18n(
"Calculating...") );
1235 kDebug(250) <<
" KFilePropsPlugin::slotSizeDetermine() properties->item()=" <<
properties->
item();
1239 d->dirSizeUpdateTimer =
new QTimer(
this);
1240 connect( d->dirSizeUpdateTimer, SIGNAL(
timeout()),
1242 d->dirSizeUpdateTimer->start(500);
1243 connect( d->dirSizeJob, SIGNAL(result(
KJob*)),
1245 d->m_sizeStopButton->setEnabled(
true);
1246 d->m_sizeDetermineButton->setEnabled(
false);
1249 if ( d->m_capacityBar )
1258 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
1266 if ( d->dirSizeJob )
1269 d->m_sizeLabel->setText(
i18n(
"At least %1",
1271 d->dirSizeJob->kill();
1274 if ( d->dirSizeUpdateTimer )
1275 d->dirSizeUpdateTimer->stop();
1277 d->m_sizeStopButton->setEnabled(
false);
1278 d->m_sizeDetermineButton->setEnabled(
true);
1293 if ( d->dirSizeJob )
1296 kDebug(250) <<
"KFilePropsPlugin::applyChanges";
1298 if (qobject_cast<QLineEdit*>(d->nameArea))
1300 QString n = ((
QLineEdit *) d->nameArea)->text();
1302 while ( ! n.isEmpty() && n[n.length()-1].isSpace() )
1303 n.truncate( n.length() - 1 );
1312 kDebug(250) <<
"oldname = " << d->oldName;
1313 kDebug(250) <<
"newname = " << n;
1314 if ( d->oldName != n || d->m_bFromTemplate ) {
1319 if (d->bDesktopFile && !newFileName.endsWith(QLatin1String(
".desktop")) &&
1320 !newFileName.endsWith(QLatin1String(
".kdelnk")))
1321 newFileName +=
".desktop";
1327 if ( !d->m_sRelativePath.isEmpty() )
1331 kDebug(250) <<
"old = " << oldurl.
url();
1334 if ( !d->m_bFromTemplate )
1339 connect( job, SIGNAL(result(
KJob*)),
1344 QEventLoop eventLoop;
1346 &eventLoop, SLOT(
quit()));
1347 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
1352 if ( !d->m_sRelativePath.isEmpty() )
1362 kDebug(250) <<
"KFilePropsPlugin::slotCopyFinished";
1381 if (d->bDesktopFile && !d->m_sRelativePath.isEmpty())
1383 kDebug(250) <<
"KFilePropsPlugin::slotCopyFinished " << d->m_sRelativePath;
1386 kDebug(250) <<
"KFilePropsPlugin::slotCopyFinished path=" << newURL.
path();
1390 if ( d->bKDesktopMode && d->bDesktopFile ) {
1394 if ( d->m_bFromTemplate ) {
1406 if (d->m_linkTargetLineEdit && !d->bMultiple) {
1408 const QString newTarget = d->m_linkTargetLineEdit->text();
1409 if (newTarget != item.
linkDest()) {
1410 kDebug(250) <<
"Updating target of symlink to" << newTarget;
1420 if ( d->m_bFromTemplate ) {
1430 fileItemList << appLink;
1439 void KFilePropsPlugin::applyIconChanges()
1441 KIconButton *iconButton = qobject_cast<KIconButton*>(d->iconArea);
1442 if ( !iconButton || !d->bIconChanged )
1466 if ( str != iconButton->
icon() )
1467 sIcon = iconButton->
icon();
1470 kDebug(250) <<
"**" << path <<
"**";
1473 if ( !sIcon.isEmpty() || QFile::exists(path) )
1476 kDebug(250) <<
"sIcon = " << (sIcon);
1477 kDebug(250) <<
"str = " << (str);
1478 cfg.desktopGroup().writeEntry(
"Icon", sIcon );
1481 cfg.reparseConfiguration();
1482 if ( cfg.desktopGroup().readEntry(
"Icon") != sIcon ) {
1484 "have sufficient access to write to <b>%1</b>.</qt>", path));
1507 class KFilePermissionsPropsPlugin::KFilePermissionsPropsPluginPrivate
1510 KFilePermissionsPropsPluginPrivate()
1513 ~KFilePermissionsPropsPluginPrivate()
1518 QCheckBox *cbRecursive;
1519 QLabel *explanationLabel;
1520 KComboBox *ownerPermCombo, *groupPermCombo, *othersPermCombo;
1521 QCheckBox *extraCheckbox;
1522 mode_t partialPermissions;
1524 bool canChangePermissions;
1526 bool hasExtendedACL;
1529 bool fileSystemSupportsACLs;
1544 #define UniOwner (S_IRUSR|S_IWUSR|S_IXUSR)
1545 #define UniGroup (S_IRGRP|S_IWGRP|S_IXGRP)
1546 #define UniOthers (S_IROTH|S_IWOTH|S_IXOTH)
1547 #define UniRead (S_IRUSR|S_IRGRP|S_IROTH)
1548 #define UniWrite (S_IWUSR|S_IWGRP|S_IWOTH)
1549 #define UniExec (S_IXUSR|S_IXGRP|S_IXOTH)
1550 #define UniSpecial (S_ISUID|S_ISGID|S_ISVTX)
1554 const mode_t KFilePermissionsPropsPlugin::standardPermissions[4] = { 0,
UniRead,
UniRead|
UniWrite, (mode_t)-1 };
1557 const char *KFilePermissionsPropsPlugin::permissionsTexts[4][4] = {
1569 I18N_NOOP(
"Can View/Read & Modify/Write"),
1577 d->cbRecursive = 0L;
1578 d->grpCombo = 0L; d->grpEdit = 0;
1584 bool IamRoot = (geteuid() == 0);
1587 bool isLink = item.
isLink();
1588 bool isDir = item.
isDir();
1589 bool hasDir = item.
isDir();
1591 d->partialPermissions = d->permissions;
1592 d->isIrregular = isIrregular(d->permissions, isDir, isLink);
1593 d->strOwner = item.
user();
1594 d->strGroup = item.
group();
1596 d->extendedACL = item.
ACL();
1598 d->fileSystemSupportsACLs =
false;
1604 KFileItemList::const_iterator it = items.begin();
1605 const KFileItemList::const_iterator kend = items.end();
1606 for ( ++it ; it != kend; ++it )
1609 if (!d->isIrregular)
1610 d->isIrregular |= isIrregular((*it).permissions(),
1611 (*it).isDir() == isDir,
1612 (*it).isLink() == isLink);
1613 d->hasExtendedACL = d->hasExtendedACL || (*it).hasExtendedACL();
1614 if ( (*it).isLink() != isLink )
1616 if ( (*it).isDir() != isDir )
1618 hasDir |= (*it).isDir();
1619 if ( (*it).permissions() != d->permissions )
1621 d->permissions &= (*it).permissions();
1622 d->partialPermissions |= (*it).permissions();
1624 if ( (*it).user() != d->strOwner )
1625 d->strOwner.clear();
1626 if ( (*it).group() != d->strGroup )
1627 d->strGroup.clear();
1641 d->partialPermissions = d->partialPermissions & ~d->permissions;
1643 bool isMyFile =
false;
1645 if (isLocal && !d->strOwner.isEmpty()) {
1646 struct passwd *myself = getpwuid( geteuid() );
1649 isMyFile = (d->strOwner == QString::fromLocal8Bit(myself->pw_name));
1651 kWarning() <<
"I don't exist ?! geteuid=" << geteuid();
1659 d->canChangePermissions = (isMyFile || IamRoot) && (!isLink);
1664 d->m_frame =
new QFrame();
1667 QBoxLayout *box =
new QVBoxLayout( d->m_frame );
1668 box->setMargin( 0 );
1677 gb =
new QGroupBox (
i18n(
"Access Permissions"), d->m_frame );
1678 box->addWidget (gb);
1680 gl =
new QGridLayout (gb);
1681 gl->setColumnStretch(1, 1);
1683 l = d->explanationLabel =
new QLabel(
"", gb );
1685 d->explanationLabel->setText(
i18np(
"This file is a link and does not have permissions.",
1686 "All files are links and do not have permissions.",
1688 else if (!d->canChangePermissions)
1689 d->explanationLabel->setText(
i18n(
"Only the owner can change permissions."));
1690 gl->addWidget(l, 0, 0, 1, 2);
1693 gl->addWidget(lbl, 1, 0, Qt::AlignRight);
1694 l = d->ownerPermCombo =
new KComboBox(gb);
1696 gl->addWidget(l, 1, 1);
1697 connect(l, SIGNAL(activated(
int)),
this, SIGNAL(
changed()));
1698 l->setWhatsThis(
i18n(
"Specifies the actions that the owner is allowed to do."));
1701 gl->addWidget(lbl, 2, 0, Qt::AlignRight);
1702 l = d->groupPermCombo =
new KComboBox(gb);
1704 gl->addWidget(l, 2, 1);
1705 connect(l, SIGNAL(activated(
int)),
this, SIGNAL(
changed()));
1706 l->setWhatsThis(
i18n(
"Specifies the actions that the members of the group are allowed to do."));
1709 gl->addWidget(lbl, 3, 0, Qt::AlignRight);
1710 l = d->othersPermCombo =
new KComboBox(gb);
1712 gl->addWidget(l, 3, 1);
1713 connect(l, SIGNAL(activated(
int)),
this, SIGNAL(
changed()));
1714 l->setWhatsThis(
i18n(
"Specifies the actions that all users, who are neither "
1715 "owner nor in the group, are allowed to do."));
1718 l = d->extraCheckbox =
new QCheckBox(hasDir ?
1719 i18n(
"Only own&er can rename and delete folder content") :
1720 i18n(
"Is &executable"),
1722 connect( d->extraCheckbox, SIGNAL(clicked()),
this, SIGNAL(
changed()) );
1723 gl->addWidget(l, 4, 1);
1724 l->setWhatsThis(hasDir ?
i18n(
"Enable this option to allow only the folder's owner to "
1725 "delete or rename the contained files and folders. Other "
1726 "users can only add new files, which requires the 'Modify "
1727 "Content' permission.")
1728 :
i18n(
"Enable this option to mark the file as executable. This only makes "
1729 "sense for programs and scripts. It is required when you want to "
1732 QLayoutItem *spacer =
new QSpacerItem(0, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
1733 gl->addItem(spacer, 5, 0, 1, 3);
1736 gl->addWidget(pbAdvancedPerm, 6, 0, 1, 2, Qt::AlignRight);
1737 connect(pbAdvancedPerm, SIGNAL(clicked()),
this, SLOT(slotShowAdvancedPermissions()));
1740 d->extraCheckbox = 0;
1745 box->addWidget (gb);
1747 gl =
new QGridLayout (gb);
1748 gl->addItem(
new QSpacerItem(0, 10), 0, 0);
1752 gl->addWidget (l, 1, 0, Qt::AlignRight);
1759 int i, maxEntries = 1000;
1760 struct passwd *user;
1765 if (IamRoot && isLocal)
1768 KCompletion *kcom = d->usrEdit->completionObject();
1771 for (i=0; ((user = getpwent()) != 0L) && (i < maxEntries); ++i)
1772 kcom->
addItem(QString::fromLatin1(user->pw_name));
1776 d->usrEdit->setText(d->strOwner);
1777 gl->addWidget(d->usrEdit, 1, 1);
1778 connect( d->usrEdit, SIGNAL(textChanged(QString)),
1783 l =
new QLabel(d->strOwner, gb);
1784 gl->addWidget(l, 1, 1);
1789 QStringList groupList;
1791 user = getpwuid(geteuid());
1793 strUser = user->pw_name;
1795 #ifdef HAVE_GETGROUPLIST
1799 QVarLengthArray<int> groups;
1801 QVarLengthArray<gid_t> groups;
1803 if (getgrouplist(strUser, user->pw_gid, NULL, &groupCount) < 0) {
1804 groups.resize(groupCount);
1806 getgrouplist(strUser, user->pw_gid, groups.data(), &groupCount);
1811 for (i = 0; i < groupCount; i++) {
1812 struct group *mygroup = getgrgid(groups[i]);
1814 groupList += QString::fromLocal8Bit(mygroup->gr_name);
1816 #endif // HAVE_GETGROUPLIST
1818 bool isMyGroup = groupList.contains(d->strGroup);
1824 groupList += d->strGroup;
1827 gl->addWidget (l, 2, 0, Qt::AlignRight);
1835 if (IamRoot && isLocal)
1840 d->grpEdit->setCompletionObject(kcom,
true);
1841 d->grpEdit->setAutoDeleteCompletionObject(
true );
1843 d->grpEdit->setText(d->strGroup);
1844 gl->addWidget(d->grpEdit, 2, 1);
1845 connect( d->grpEdit, SIGNAL(textChanged(QString)),
1848 else if ((groupList.count() > 1) && isMyFile && isLocal)
1851 d->grpCombo->setObjectName(QLatin1String(
"combogrouplist"));
1852 d->grpCombo->addItems(groupList);
1853 d->grpCombo->setCurrentIndex(groupList.indexOf(d->strGroup));
1854 gl->addWidget(d->grpCombo, 2, 1);
1855 connect( d->grpCombo, SIGNAL(activated(
int)),
1860 l =
new QLabel(d->strGroup, gb);
1861 gl->addWidget(l, 2, 1);
1864 gl->setColumnStretch(2, 10);
1867 if ( hasDir && !isLink && !isTrash )
1869 d->cbRecursive =
new QCheckBox(
i18n(
"Apply changes to all subfolders and their contents"), d->m_frame );
1870 connect( d->cbRecursive, SIGNAL(clicked()),
this, SIGNAL(
changed()) );
1871 box->addWidget( d->cbRecursive );
1874 updateAccessControls();
1880 enableAccessControls(
false);
1881 if ( pbAdvancedPerm)
1882 pbAdvancedPerm->setEnabled(
false);
1885 box->addStretch (10);
1888 #ifdef HAVE_POSIX_ACL
1889 static bool fileSystemSupportsACL(
const QByteArray& path )
1891 bool fileSystemSupportsACLs =
false;
1894 fileSystemSupportsACLs = ( statfs( path.data(), &buf ) == 0 ) && ( buf.f_flags & MNT_ACLS );
1896 fileSystemSupportsACLs =
1897 getxattr( path.data(),
"system.posix_acl_access", NULL, 0 ) >= 0 || errno == ENODATA;
1899 return fileSystemSupportsACLs;
1904 void KFilePermissionsPropsPlugin::slotShowAdvancedPermissions() {
1908 dlg.setModal(
true );
1909 dlg.setCaption(
i18n(
"Advanced Permissions") );
1917 QVBoxLayout *vbox =
new QVBoxLayout(mainw);
1920 vbox->addWidget(gb);
1922 gl =
new QGridLayout (gb);
1923 gl->addItem(
new QSpacerItem(0, 10), 0, 0);
1925 QVector<QWidget*> theNotSpecials;
1928 gl->addWidget(l, 1, 0);
1929 theNotSpecials.append( l );
1935 gl->addWidget (l, 1, 1);
1936 theNotSpecials.append( l );
1937 QString readWhatsThis;
1939 readWhatsThis =
i18n(
"This flag allows viewing the content of the folder.");
1941 readWhatsThis =
i18n(
"The Read flag allows viewing the content of the file.");
1942 l->setWhatsThis(readWhatsThis);
1945 l =
new QLabel(
i18n(
"Write\nEntries"), gb );
1948 gl->addWidget (l, 1, 2);
1949 theNotSpecials.append( l );
1950 QString writeWhatsThis;
1952 writeWhatsThis =
i18n(
"This flag allows adding, renaming and deleting of files. "
1953 "Note that deleting and renaming can be limited using the Sticky flag.");
1955 writeWhatsThis =
i18n(
"The Write flag allows modifying the content of the file.");
1956 l->setWhatsThis(writeWhatsThis);
1958 QString execWhatsThis;
1960 l =
new QLabel(
i18nc(
"Enter folder",
"Enter"), gb );
1961 execWhatsThis =
i18n(
"Enable this flag to allow entering the folder.");
1965 execWhatsThis =
i18n(
"Enable this flag to allow executing the file as a program.");
1967 l->setWhatsThis(execWhatsThis);
1968 theNotSpecials.append( l );
1970 QSize size = l->sizeHint();
1971 size.setWidth(size.width() + 15);
1972 l->setFixedSize(size);
1973 gl->addWidget (l, 1, 3);
1976 gl->addWidget(l, 1, 4, 1, 2);
1977 QString specialWhatsThis;
1979 specialWhatsThis =
i18n(
"Special flag. Valid for the whole folder, the exact "
1980 "meaning of the flag can be seen in the right hand column.");
1982 specialWhatsThis =
i18n(
"Special flag. The exact meaning of the flag can be seen "
1983 "in the right hand column.");
1984 l->setWhatsThis(specialWhatsThis);
1987 gl->addWidget (cl[0], 2, 0);
1988 theNotSpecials.append( cl[0] );
1991 gl->addWidget (cl[1], 3, 0);
1992 theNotSpecials.append( cl[1] );
1995 gl->addWidget (cl[2], 4, 0);
1996 theNotSpecials.append( cl[2] );
1999 gl->addWidget(l, 2, 5);
2000 QString setUidWhatsThis;
2002 setUidWhatsThis =
i18n(
"If this flag is set, the owner of this folder will be "
2003 "the owner of all new files.");
2005 setUidWhatsThis =
i18n(
"If this file is an executable and the flag is set, it will "
2006 "be executed with the permissions of the owner.");
2007 l->setWhatsThis(setUidWhatsThis);
2010 gl->addWidget(l, 3, 5);
2011 QString setGidWhatsThis;
2013 setGidWhatsThis =
i18n(
"If this flag is set, the group of this folder will be "
2014 "set for all new files.");
2016 setGidWhatsThis =
i18n(
"If this file is an executable and the flag is set, it will "
2017 "be executed with the permissions of the group.");
2018 l->setWhatsThis(setGidWhatsThis);
2020 l =
new QLabel(
i18nc(
"File permission",
"Sticky"), gb);
2021 gl->addWidget(l, 4, 5);
2022 QString stickyWhatsThis;
2024 stickyWhatsThis =
i18n(
"If the Sticky flag is set on a folder, only the owner "
2025 "and root can delete or rename files. Otherwise everybody "
2026 "with write permissions can do this.");
2028 stickyWhatsThis =
i18n(
"The Sticky flag on a file is ignored on Linux, but may "
2029 "be used on some systems");
2030 l->setWhatsThis(stickyWhatsThis);
2032 mode_t aPermissions, aPartialPermissions;
2033 mode_t dummy1, dummy2;
2035 if (!d->isIrregular) {
2038 getPermissionMasks(aPartialPermissions,
2045 getPermissionMasks(dummy1,
2046 aPartialPermissions,
2052 aPartialPermissions = 0;
2057 aPermissions = d->permissions;
2058 aPartialPermissions = d->partialPermissions;
2062 QCheckBox *cba[3][4];
2063 for (
int row = 0; row < 3 ; ++row) {
2064 for (
int col = 0; col < 4; ++col) {
2065 QCheckBox *cb =
new QCheckBox(gb);
2066 if ( col != 3 ) theNotSpecials.append( cb );
2068 cb->setChecked(aPermissions & fperm[row][col]);
2069 if ( aPartialPermissions & fperm[row][col] )
2072 cb->setCheckState(Qt::PartiallyChecked);
2074 else if (d->cbRecursive && d->cbRecursive->isChecked())
2077 cb->setEnabled( d->canChangePermissions );
2078 gl->addWidget (cb, row+2, col+1);
2081 cb->setWhatsThis(readWhatsThis);
2084 cb->setWhatsThis(writeWhatsThis);
2087 cb->setWhatsThis(execWhatsThis);
2092 cb->setWhatsThis(setUidWhatsThis);
2095 cb->setWhatsThis(setGidWhatsThis);
2098 cb->setWhatsThis(stickyWhatsThis);
2105 gl->setColumnStretch(6, 10);
2107 #ifdef HAVE_POSIX_ACL
2108 KACLEditWidget *extendedACLs = 0;
2113 d->fileSystemSupportsACLs = fileSystemSupportsACL( path );
2115 if ( d->fileSystemSupportsACLs ) {
2116 std::for_each( theNotSpecials.begin(), theNotSpecials.end(), std::mem_fun( &QWidget::hide ) );
2117 extendedACLs =
new KACLEditWidget( mainw );
2118 vbox->addWidget(extendedACLs);
2119 if ( d->extendedACL.isValid() && d->extendedACL.isExtended() )
2120 extendedACLs->setACL( d->extendedACL );
2122 extendedACLs->setACL(
KACL( aPermissions ) );
2124 if ( d->defaultACL.isValid() )
2125 extendedACLs->setDefaultACL( d->defaultACL );
2128 extendedACLs->setAllowDefaults(
true );
2131 dlg.setMainWidget( mainw );
2132 if (dlg.exec() != KDialog::Accepted)
2135 mode_t andPermissions = mode_t(~0);
2136 mode_t orPermissions = 0;
2137 for (
int row = 0; row < 3; ++row)
2138 for (
int col = 0; col < 4; ++col) {
2139 switch (cba[row][col]->checkState())
2142 orPermissions |= fperm[row][col];
2145 andPermissions &= ~fperm[row][col];
2152 d->isIrregular =
false;
2154 KFileItemList::const_iterator it = items.begin();
2155 const KFileItemList::const_iterator kend = items.end();
2156 for ( ; it != kend; ++it ) {
2157 if (isIrregular(((*it).permissions() & andPermissions) | orPermissions,
2158 (*it).isDir(), (*it).isLink())) {
2159 d->isIrregular =
true;
2164 d->permissions = orPermissions;
2165 d->partialPermissions = andPermissions;
2167 #ifdef HAVE_POSIX_ACL
2169 if ( extendedACLs ) {
2170 d->extendedACL = extendedACLs->getACL();
2171 d->defaultACL = extendedACLs->getDefaultACL();
2172 d->hasExtendedACL = d->extendedACL.isExtended() || d->defaultACL.isValid();
2173 d->permissions = d->extendedACL.basePermissions();
2174 d->permissions |= ( andPermissions | orPermissions ) & ( S_ISUID|S_ISGID|S_ISVTX );
2178 updateAccessControls();
2198 void KFilePermissionsPropsPlugin::setComboContent(
QComboBox *combo, PermissionsTarget target,
2199 mode_t permissions, mode_t partial) {
2205 combo->addItem(
i18n(
"Link"));
2206 combo->setCurrentIndex(0);
2210 mode_t tMask = permissionsMasks[target];
2212 for (textIndex = 0; standardPermissions[textIndex] != (mode_t)-1; textIndex++) {
2213 if ((standardPermissions[textIndex]&tMask) == (permissions&tMask&(
UniRead|
UniWrite)))
2216 Q_ASSERT(standardPermissions[textIndex] != (mode_t)-1);
2218 for (
int i = 0; permissionsTexts[(int)d->pmode][i]; i++)
2219 combo->addItem(
i18n(permissionsTexts[(
int)d->pmode][i]));
2221 if (partial & tMask & ~
UniExec) {
2222 combo->addItem(
i18n(
"Varying (No Change)"));
2223 combo->setCurrentIndex(3);
2226 combo->setCurrentIndex(textIndex);
2231 bool KFilePermissionsPropsPlugin::isIrregular(mode_t permissions,
bool isDir,
bool isLink) {
2235 mode_t p = permissions;
2236 if (p & (S_ISUID | S_ISGID))
2243 if ((p0 != 0) && (p0 != (S_IRUSR | S_IXUSR)) && (p0 !=
UniOwner))
2246 if ((p0 != 0) && (p0 != (S_IRGRP | S_IXGRP)) && (p0 !=
UniGroup))
2249 if ((p0 != 0) && (p0 != (S_IROTH | S_IXOTH)) && (p0 !=
UniOthers))
2258 bool usrXPossible = !p0;
2260 if ((p0 == S_IXUSR) || (p0 == (S_IWUSR | S_IXUSR)))
2262 usrXPossible =
true;
2264 else if (p0 == S_IWUSR)
2268 bool grpXPossible = !p0;
2270 if ((p0 == S_IXGRP) || (p0 == (S_IWGRP | S_IXGRP)))
2272 grpXPossible =
true;
2274 else if (p0 == S_IWGRP)
2277 grpXPossible =
true;
2280 bool othXPossible = !p0;
2282 if ((p0 == S_IXOTH) || (p0 == (S_IWOTH | S_IXOTH)))
2284 othXPossible =
true;
2286 else if (p0 == S_IWOTH)
2290 return (p &
UniExec) && !(usrXPossible && grpXPossible && othXPossible);
2294 void KFilePermissionsPropsPlugin::enableAccessControls(
bool enable) {
2295 d->ownerPermCombo->setEnabled(enable);
2296 d->groupPermCombo->setEnabled(enable);
2297 d->othersPermCombo->setEnabled(enable);
2298 if (d->extraCheckbox)
2299 d->extraCheckbox->setEnabled(enable);
2300 if ( d->cbRecursive )
2301 d->cbRecursive->setEnabled(enable);
2305 void KFilePermissionsPropsPlugin::updateAccessControls() {
2307 d->permissions, d->partialPermissions);
2309 d->permissions, d->partialPermissions);
2311 d->permissions, d->partialPermissions);
2315 enableAccessControls(
false);
2318 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2319 if (d->canChangePermissions)
2320 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2321 i18np(
"This file uses advanced permissions",
2322 "These files use advanced permissions.",
2324 if (d->partialPermissions &
UniExec) {
2325 d->extraCheckbox->setTristate();
2326 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
2329 d->extraCheckbox->setTristate(
false);
2330 d->extraCheckbox->setChecked(d->permissions &
UniExec);
2334 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2337 if ( d->cbRecursive )
2338 d->cbRecursive->setEnabled( d->canChangePermissions && !d->isIrregular );
2340 if (d->canChangePermissions)
2341 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2342 i18np(
"This folder uses advanced permissions.",
2343 "These folders use advanced permissions.",
2345 if (d->partialPermissions & S_ISVTX) {
2346 d->extraCheckbox->setTristate();
2347 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
2350 d->extraCheckbox->setTristate(
false);
2351 d->extraCheckbox->setChecked(d->permissions & S_ISVTX);
2355 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2356 if (d->canChangePermissions)
2357 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2358 i18n(
"These files use advanced permissions.") :
"");
2360 if (d->partialPermissions & S_ISVTX) {
2361 d->extraCheckbox->setTristate();
2362 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
2365 d->extraCheckbox->setTristate(
false);
2366 d->extraCheckbox->setChecked(d->permissions & S_ISVTX);
2373 void KFilePermissionsPropsPlugin::getPermissionMasks(mode_t &andFilePermissions,
2374 mode_t &andDirPermissions,
2375 mode_t &orFilePermissions,
2376 mode_t &orDirPermissions) {
2378 andDirPermissions = mode_t(~(S_ISUID|S_ISGID));
2379 orFilePermissions = 0;
2380 orDirPermissions = 0;
2384 mode_t m = standardPermissions[d->ownerPermCombo->currentIndex()];
2385 if (m != (mode_t) -1) {
2389 ((d->pmode ==
PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
2390 andFilePermissions &= ~(S_IRUSR | S_IWUSR);
2392 andFilePermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2393 if ((m & S_IRUSR) && (d->extraCheckbox->checkState() == Qt::Checked))
2394 orFilePermissions |= S_IXUSR;
2399 orDirPermissions |= S_IXUSR;
2400 andDirPermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2403 m = standardPermissions[d->groupPermCombo->currentIndex()];
2404 if (m != (mode_t) -1) {
2408 ((d->pmode ==
PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
2409 andFilePermissions &= ~(S_IRGRP | S_IWGRP);
2411 andFilePermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2412 if ((m & S_IRGRP) && (d->extraCheckbox->checkState() == Qt::Checked))
2413 orFilePermissions |= S_IXGRP;
2418 orDirPermissions |= S_IXGRP;
2419 andDirPermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2422 m = d->othersPermCombo->currentIndex() >= 0 ? standardPermissions[d->othersPermCombo->currentIndex()] : (mode_t)-1;
2423 if (m != (mode_t) -1) {
2427 ((d->pmode ==
PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
2428 andFilePermissions &= ~(S_IROTH | S_IWOTH);
2430 andFilePermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2431 if ((m & S_IROTH) && (d->extraCheckbox->checkState() == Qt::Checked))
2432 orFilePermissions |= S_IXOTH;
2437 orDirPermissions |= S_IXOTH;
2438 andDirPermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2442 (d->extraCheckbox->checkState() != Qt::PartiallyChecked)) {
2443 andDirPermissions &= ~S_ISVTX;
2444 if (d->extraCheckbox->checkState() == Qt::Checked)
2445 orDirPermissions |= S_ISVTX;
2451 mode_t orFilePermissions;
2452 mode_t orDirPermissions;
2453 mode_t andFilePermissions;
2454 mode_t andDirPermissions;
2456 if (!d->canChangePermissions)
2459 if (!d->isIrregular)
2460 getPermissionMasks(andFilePermissions,
2465 orFilePermissions = d->permissions;
2466 andFilePermissions = d->partialPermissions;
2467 orDirPermissions = d->permissions;
2468 andDirPermissions = d->partialPermissions;
2471 QString owner,
group;
2473 owner = d->usrEdit->text();
2475 group = d->grpEdit->text();
2476 else if (d->grpCombo)
2477 group = d->grpCombo->currentText();
2479 if (owner == d->strOwner)
2482 if (
group == d->strGroup)
2485 bool recursive = d->cbRecursive && d->cbRecursive->isChecked();
2486 bool permissionChange =
false;
2490 KFileItemList::const_iterator it = items.begin();
2491 const KFileItemList::const_iterator kend = items.end();
2492 for ( ; it != kend; ++it ) {
2493 if ((*it).isDir()) {
2495 if ((*it).permissions() != (((*it).permissions() & andDirPermissions) | orDirPermissions))
2496 permissionChange =
true;
2498 else if ((*it).isFile()) {
2500 if ((*it).permissions() != (((*it).permissions() & andFilePermissions) | orFilePermissions))
2501 permissionChange =
true;
2508 if (owner.isEmpty() &&
group.isEmpty() && !recursive
2509 && !permissionChange && !ACLChange && !defaultACLChange)
2513 if (files.count() > 0) {
2514 job =
KIO::chmod( files, orFilePermissions, ~andFilePermissions,
2515 owner,
group,
false );
2516 if ( ACLChange && d->fileSystemSupportsACLs )
2517 job->
addMetaData(
"ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():
"ACL_DELETE" );
2518 if ( defaultACLChange && d->fileSystemSupportsACLs )
2519 job->
addMetaData(
"DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():
"ACL_DELETE" );
2521 connect( job, SIGNAL(result(
KJob*)),
2522 SLOT(slotChmodResult(
KJob*)) );
2523 QEventLoop eventLoop;
2525 &eventLoop, SLOT(
quit()));
2526 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
2528 if (
dirs.count() > 0) {
2530 owner,
group, recursive );
2531 if ( ACLChange && d->fileSystemSupportsACLs )
2532 job->
addMetaData(
"ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():
"ACL_DELETE" );
2533 if ( defaultACLChange && d->fileSystemSupportsACLs )
2534 job->
addMetaData(
"DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():
"ACL_DELETE" );
2536 connect( job, SIGNAL(result(
KJob*)),
2537 SLOT(slotChmodResult(
KJob*)) );
2538 QEventLoop eventLoop;
2540 &eventLoop, SLOT(
quit()));
2541 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
2545 void KFilePermissionsPropsPlugin::slotChmodResult(
KJob * job )
2547 kDebug(250) <<
"KFilePermissionsPropsPlugin::slotChmodResult";
2557 class KUrlPropsPlugin::KUrlPropsPluginPrivate
2560 KUrlPropsPluginPrivate()
2563 ~KUrlPropsPluginPrivate()
2575 d->m_frame =
new QFrame();
2577 QVBoxLayout *layout =
new QVBoxLayout(d->m_frame);
2578 layout->setMargin(0);
2581 l =
new QLabel( d->m_frame );
2582 l->setObjectName( QLatin1String(
"Label_1" ) );
2583 l->setText(
i18n(
"URL:") );
2584 layout->addWidget(l, Qt::AlignRight);
2587 layout->addWidget(d->URLEdit);
2594 if ( !
f.open( QIODevice::ReadOnly ) ) {
2603 if (!d->URLStr.isEmpty()) {
2604 d->URLEdit->setUrl(
KUrl(d->URLStr) );
2608 connect( d->URLEdit, SIGNAL(textChanged(QString)),
2611 layout->addStretch (1);
2626 if ( _items.count() != 1 )
2641 return config.hasLinkType();
2654 if ( !
f.open( QIODevice::ReadWrite ) ) {
2656 "sufficient access to write to <b>%1</b>.</qt>", path));
2663 dg.
writeEntry(
"Type", QString::fromLatin1(
"Link"));
2683 class KDevicePropsPlugin::KDevicePropsPluginPrivate
2686 KDevicePropsPluginPrivate()
2689 ~KDevicePropsPluginPrivate()
2693 bool isMounted()
const {
2694 const QString dev = device->currentText();
2699 QStringList mountpointlist;
2701 QLabel *m_freeSpaceLabel;
2702 QProgressBar *m_freeSpaceBar;
2706 QCheckBox* readonly;
2708 QStringList m_devicelist;
2713 d->m_frame =
new QFrame();
2716 QStringList devices;
2719 for(KMountPoint::List::ConstIterator it = mountPoints.begin();
2720 it != mountPoints.end(); ++it)
2723 QString mountPoint = mp->mountPoint();
2724 QString device = mp->mountedFrom();
2725 kDebug()<<
"mountPoint :"<<mountPoint<<
" device :"<<device<<
" mp->mountType() :"<<mp->mountType();
2727 if ((mountPoint !=
"-") && (mountPoint !=
"none") && !mountPoint.isEmpty()
2728 && device !=
"none")
2730 devices.append( device + QString::fromLatin1(
" (")
2731 + mountPoint + QString::fromLatin1(
")") );
2732 d->m_devicelist.append(device);
2733 d->mountpointlist.append(mountPoint);
2737 QGridLayout *layout =
new QGridLayout( d->m_frame );
2739 layout->setMargin(0);
2740 layout->setColumnStretch(1, 1);
2744 label->setText( devices.count() == 0 ?
2745 i18n(
"Device (/dev/fd0):") :
2747 layout->addWidget(
label, 0, 0, Qt::AlignRight);
2749 d->device =
new KComboBox( d->m_frame );
2750 d->device->setObjectName( QLatin1String(
"ComboBox_device" ) );
2751 d->device->setEditable(
true );
2752 d->device->addItems( devices );
2753 layout->addWidget(d->device, 0, 1);
2754 connect( d->device, SIGNAL(activated(
int)),
2755 this, SLOT(slotActivated(
int)) );
2757 d->readonly =
new QCheckBox( d->m_frame );
2758 d->readonly->setObjectName( QLatin1String(
"CheckBox_readonly" ) );
2759 d->readonly->setText(
i18n(
"Read only") );
2760 layout->addWidget(d->readonly, 1, 1);
2764 layout->addWidget(
label, 2, 0, Qt::AlignRight);
2767 layout->addWidget(fileSystem, 2, 1);
2770 label->setText( devices.count()==0 ?
2771 i18n(
"Mount point (/mnt/floppy):") :
2772 i18n(
"Mount point:"));
2773 layout->addWidget(
label, 3, 0, Qt::AlignRight);
2775 d->mountpoint =
new QLabel( d->m_frame );
2776 d->mountpoint->setObjectName( QLatin1String(
"LineEdit_mountpoint" ) );
2778 layout->addWidget(d->mountpoint, 3, 1);
2781 d->m_freeSpaceText =
new QLabel(
i18n(
"Device usage:"), d->m_frame );
2782 layout->addWidget(d->m_freeSpaceText, 4, 0, Qt::AlignRight);
2784 d->m_freeSpaceLabel =
new QLabel( d->m_frame );
2785 layout->addWidget( d->m_freeSpaceLabel, 4, 1 );
2787 d->m_freeSpaceBar =
new QProgressBar( d->m_frame );
2788 d->m_freeSpaceBar->setObjectName(
"freeSpaceBar" );
2789 layout->addWidget(d->m_freeSpaceBar, 5, 0, 1, 2);
2792 d->m_freeSpaceText->hide();
2793 d->m_freeSpaceLabel->hide();
2794 d->m_freeSpaceBar->hide();
2797 layout->addWidget(sep, 6, 0, 1, 2);
2799 layout->setRowStretch(7, 1);
2808 if ( !
f.open( QIODevice::ReadOnly ) )
2814 QString deviceStr =
config.readEntry(
"Dev" );
2815 QString mountPointStr =
config.readEntry(
"MountPoint" );
2816 bool ro =
config.readEntry(
"ReadOnly",
false );
2818 fileSystem->setText(
config.readEntry(
"FSType"));
2820 d->device->setEditText( deviceStr );
2821 if ( !deviceStr.isEmpty() ) {
2823 int index = d->m_devicelist.indexOf(deviceStr);
2827 slotActivated( index );
2831 if ( !mountPointStr.isEmpty() )
2833 d->mountpoint->setText( mountPointStr );
2837 d->readonly->setChecked( ro );
2839 connect( d->device, SIGNAL(activated(
int)),
2841 connect( d->device, SIGNAL(textChanged(QString)),
2843 connect( d->readonly, SIGNAL(toggled(
bool)),
2846 connect( d->device, SIGNAL(textChanged(QString)),
2847 this, SLOT(slotDeviceChanged()) );
2860 void KDevicePropsPlugin::updateInfo()
2863 d->m_freeSpaceText->hide();
2864 d->m_freeSpaceLabel->hide();
2865 d->m_freeSpaceBar->hide();
2867 if (!d->mountpoint->text().isEmpty() && d->isMounted()) {
2868 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( d->mountpoint->text() );
2869 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
2873 void KDevicePropsPlugin::slotActivated(
int index )
2877 if (index < d->m_devicelist.count()) {
2879 d->device->setEditText(d->m_devicelist[index]);
2880 d->mountpoint->setText(d->mountpointlist[index]);
2886 void KDevicePropsPlugin::slotDeviceChanged()
2889 int index = d->m_devicelist.indexOf( d->device->currentText() );
2891 d->mountpoint->setText( d->mountpointlist[index] );
2893 d->mountpoint->setText( QString() );
2898 void KDevicePropsPlugin::slotFoundMountPoint(
const QString&,
2903 d->m_freeSpaceText->show();
2904 d->m_freeSpaceLabel->show();
2906 const int percUsed = kibSize != 0 ? (100 - (int)(100.0 * kibAvail / kibSize)) : 100;
2908 d->m_freeSpaceLabel->setText(
2909 i18nc(
"Available space out of total partition size (percent used)",
"%1 free of %2 (%3% used)",
2914 d->m_freeSpaceBar->setRange(0, 100);
2915 d->m_freeSpaceBar->setValue(percUsed);
2916 d->m_freeSpaceBar->show();
2921 if ( _items.count() != 1 )
2936 return config.hasDeviceType();
2947 if ( !
f.open( QIODevice::ReadWrite ) )
2950 "access to write to <b>%1</b>.</qt>", path));
2957 config.writeEntry(
"Type", QString::fromLatin1(
"FSDevice") );
2959 config.writeEntry(
"Dev", d->device->currentText() );
2960 config.writeEntry(
"MountPoint", d->mountpoint->text() );
2962 config.writeEntry(
"ReadOnly", d->readonly->isChecked() );
2974 class KDesktopPropsPlugin::KDesktopPropsPluginPrivate
2977 KDesktopPropsPluginPrivate()
2978 : w( new Ui_KPropertiesDesktopBase )
2979 , m_frame( new
QFrame() )
2982 ~KDesktopPropsPluginPrivate()
2986 Ui_KPropertiesDesktopBase* w;
2989 QString m_origCommandStr;
2990 QString m_terminalOptionStr;
2991 QString m_suidUserStr;
2992 QString m_dbusStartupType;
2993 QString m_dbusServiceName;
2994 QString m_origDesktopFile;
2995 bool m_terminalBool;
3004 d->w->setupUi(d->m_frame);
3014 d->w->nameEdit->hide();
3015 d->w->nameLabel->hide();
3019 d->w->pathEdit->lineEdit()->setAcceptDrops(
false);
3021 connect( d->w->nameEdit, SIGNAL(textChanged(QString)),
this, SIGNAL(
changed()) );
3022 connect( d->w->genNameEdit, SIGNAL(textChanged(QString)),
this, SIGNAL(
changed()) );
3023 connect( d->w->commentEdit, SIGNAL(textChanged(QString)),
this, SIGNAL(
changed()) );
3024 connect( d->w->commandEdit, SIGNAL(textChanged(QString)),
this, SIGNAL(
changed()) );
3025 connect( d->w->pathEdit, SIGNAL(textChanged(QString)),
this, SIGNAL(
changed()) );
3027 connect( d->w->browseButton, SIGNAL(clicked()),
this, SLOT(
slotBrowseExec()) );
3028 connect( d->w->addFiletypeButton, SIGNAL(clicked()),
this, SLOT(
slotAddFiletype()) );
3029 connect( d->w->delFiletypeButton, SIGNAL(clicked()),
this, SLOT(
slotDelFiletype()) );
3030 connect( d->w->advancedButton, SIGNAL(clicked()),
this, SLOT(
slotAdvanced()) );
3041 QFile
f( d->m_origDesktopFile );
3042 if ( !
f.open( QIODevice::ReadOnly ) )
3048 QString nameStr = _config.
readName();
3051 QString commandStr =
config.readEntry(
"Exec", QString() );
3052 if (commandStr.startsWith(QLatin1String(
"ksystraycmd ")))
3054 commandStr.remove(0, 12);
3055 d->m_systrayBool =
true;
3058 d->m_systrayBool =
false;
3060 d->m_origCommandStr = commandStr;
3061 QString pathStr =
config.readEntry(
"Path", QString() );
3062 d->m_terminalBool =
config.readEntry(
"Terminal",
false );
3063 d->m_terminalOptionStr =
config.readEntry(
"TerminalOptions" );
3064 d->m_suidBool =
config.readEntry(
"X-KDE-SubstituteUID",
false );
3065 d->m_suidUserStr =
config.readEntry(
"X-KDE-Username" );
3066 if(
config.hasKey(
"StartupNotify" ))
3067 d->m_startupBool =
config.readEntry(
"StartupNotify",
true );
3069 d->m_startupBool =
config.readEntry(
"X-KDE-StartupNotify",
true );
3070 d->m_dbusStartupType =
config.readEntry(
"X-DBUS-StartupType").toLower();
3073 d->m_dbusServiceName =
config.readEntry(
"X-DBUS-ServiceName");
3077 if ( nameStr.isEmpty() || bKDesktopMode ) {
3083 if ( !bKDesktopMode )
3084 d->w->nameEdit->setText(nameStr);
3086 d->w->genNameEdit->setText( genNameStr );
3087 d->w->commentEdit->setText( commentStr );
3088 d->w->commandEdit->setText( commandStr );
3089 d->w->pathEdit->lineEdit()->setText( pathStr );
3095 for(QStringList::ConstIterator it =
mimeTypes.begin();
3104 (*it).toInt(&numeric);
3113 QTreeWidgetItem *item =
new QTreeWidgetItem();
3114 item->setText(0, p->name());
3115 item->setText(1, p->comment());
3116 item->setText(2, preference);
3117 d->w->filetypeList->addTopLevelItem(item);
3120 d->w->filetypeList->resizeColumnToContents(0);
3132 i18n(
"Select one or more file types to add:"),
3139 if (dlg.exec() == KDialog::Accepted)
3148 int count = d->w->filetypeList->topLevelItemCount();
3149 for (
int i = 0; !found && i < count; ++i) {
3150 if (d->w->filetypeList->topLevelItem(i)->text(0) ==
mimetype) {
3155 QTreeWidgetItem *item =
new QTreeWidgetItem();
3156 item->setText(0, p->name());
3157 item->setText(1, p->comment());
3158 d->w->filetypeList->addTopLevelItem(item);
3160 d->w->filetypeList->resizeColumnToContents(0);
3168 QTreeWidgetItem *cur = d->w->filetypeList->currentItem();
3175 void KDesktopPropsPlugin::checkCommandChanged()
3180 d->m_origCommandStr = d->w->commandEdit->text();
3181 d->m_dbusStartupType.clear();
3182 d->m_dbusServiceName.clear();
3188 kDebug(250) <<
"KDesktopPropsPlugin::applyChanges";
3199 if ( !
f.open( QIODevice::ReadWrite ) ) {
3201 "sufficient access to write to <b>%1</b>.</qt>", path));
3208 checkCommandChanged();
3211 QScopedPointer<KDesktopFile> _config (origConfig.
copyTo(path));
3213 config.writeEntry(
"Type", QString::fromLatin1(
"Application"));
3214 config.writeEntry(
"Comment", d->w->commentEdit->text() );
3216 config.writeEntry(
"GenericName", d->w->genNameEdit->text() );
3219 if (d->m_systrayBool)
3220 config.writeEntry(
"Exec", d->w->commandEdit->text().prepend(
"ksystraycmd ") );
3222 config.writeEntry(
"Exec", d->w->commandEdit->text() );
3223 config.writeEntry(
"Path", d->w->pathEdit->lineEdit()->text() );
3227 int count = d->w->filetypeList->topLevelItemCount();
3228 for (
int i = 0; i < count; ++i) {
3229 QTreeWidgetItem *item = d->w->filetypeList->topLevelItem(i);
3230 QString preference = item->text(2);
3232 if (!preference.isEmpty())
3239 if ( !d->w->nameEdit->isHidden() ) {
3240 QString nameStr = d->w->nameEdit->text();
3241 config.writeEntry(
"Name", nameStr );
3245 config.writeEntry(
"Terminal", d->m_terminalBool);
3246 config.writeEntry(
"TerminalOptions", d->m_terminalOptionStr);
3247 config.writeEntry(
"X-KDE-SubstituteUID", d->m_suidBool);
3248 config.writeEntry(
"X-KDE-Username", d->m_suidUserStr);
3249 config.writeEntry(
"StartupNotify", d->m_startupBool);
3250 config.writeEntry(
"X-DBUS-StartupType", d->m_dbusStartupType);
3251 config.writeEntry(
"X-DBUS-ServiceName", d->m_dbusServiceName);
3256 bool updateNeeded = !sycocaPath.startsWith(
'/');
3260 updateNeeded = !sycocaPath.startsWith(
'/');
3270 QString(), d->m_frame );
3274 if ( !
f.isLocalFile()) {
3279 QString path =
f.toLocalFile();
3281 d->w->commandEdit->setText( path );
3287 dlg.setObjectName(
"KPropertiesDesktopAdv" );
3288 dlg.setModal(
true );
3292 Ui_KPropertiesDesktopAdvBase w;
3297 checkCommandChanged();
3302 QString preferredTerminal = confGroup.
readPathEntry(
"TerminalApplication",
3303 QString::fromLatin1(
"konsole"));
3305 bool terminalCloseBool =
false;
3307 if (preferredTerminal ==
"konsole")
3309 terminalCloseBool = (d->m_terminalOptionStr.contains(
"--noclose" ) > 0);
3310 w.terminalCloseCheck->setChecked(terminalCloseBool);
3311 d->m_terminalOptionStr.remove(
"--noclose");
3315 w.terminalCloseCheck->hide();
3318 w.terminalCheck->setChecked(d->m_terminalBool);
3319 w.terminalEdit->setText(d->m_terminalOptionStr);
3320 w.terminalCloseCheck->setEnabled(d->m_terminalBool);
3321 w.terminalEdit->setEnabled(d->m_terminalBool);
3322 w.terminalEditLabel->setEnabled(d->m_terminalBool);
3324 w.suidCheck->setChecked(d->m_suidBool);
3325 w.suidEdit->setText(d->m_suidUserStr);
3326 w.suidEdit->setEnabled(d->m_suidBool);
3327 w.suidEditLabel->setEnabled(d->m_suidBool);
3329 w.startupInfoCheck->setChecked(d->m_startupBool);
3330 w.systrayCheck->setChecked(d->m_systrayBool);
3332 if (d->m_dbusStartupType ==
"unique")
3333 w.dbusCombo->setCurrentIndex(2);
3334 else if (d->m_dbusStartupType ==
"multi")
3335 w.dbusCombo->setCurrentIndex(1);
3336 else if (d->m_dbusStartupType ==
"wait")
3337 w.dbusCombo->setCurrentIndex(3);
3339 w.dbusCombo->setCurrentIndex(0);
3345 int i, maxEntries = 1000;
3347 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
3348 kcom->
addItem(QString::fromLatin1(pw->pw_name));
3352 w.suidEdit->setCompletionObject(kcom,
true);
3353 w.suidEdit->setAutoDeleteCompletionObject(
true );
3361 connect( w.terminalEdit, SIGNAL(textChanged(QString)),
3363 connect( w.terminalCloseCheck, SIGNAL(toggled(
bool)),
3365 connect( w.terminalCheck, SIGNAL(toggled(
bool)),
3367 connect( w.suidCheck, SIGNAL(toggled(
bool)),
3369 connect( w.suidEdit, SIGNAL(textChanged(QString)),
3371 connect( w.startupInfoCheck, SIGNAL(toggled(
bool)),
3373 connect( w.systrayCheck, SIGNAL(toggled(
bool)),
3375 connect( w.dbusCombo, SIGNAL(activated(
int)),
3378 if ( dlg.exec() == QDialog::Accepted )
3380 d->m_terminalOptionStr = w.terminalEdit->text().trimmed();
3381 d->m_terminalBool = w.terminalCheck->isChecked();
3382 d->m_suidBool = w.suidCheck->isChecked();
3383 d->m_suidUserStr = w.suidEdit->text().trimmed();
3384 d->m_startupBool = w.startupInfoCheck->isChecked();
3385 d->m_systrayBool = w.systrayCheck->isChecked();
3387 if (w.terminalCloseCheck->isChecked())
3389 d->m_terminalOptionStr.append(
" --noclose");
3392 switch(w.dbusCombo->currentIndex())
3394 case 1: d->m_dbusStartupType =
"multi";
break;
3395 case 2: d->m_dbusStartupType =
"unique";
break;
3396 case 3: d->m_dbusStartupType =
"wait";
break;
3397 default: d->m_dbusStartupType =
"none";
break;
3404 if ( _items.count() != 1 ) {
3423 return config.hasApplicationType() &&
3428 #include "kpropertiesdialog.moc"
3429 #include "kpropertiesdialog_p.moc"