00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include "kpropertiesdialog.h"
00045 #include "kpropertiesdialog_p.h"
00046
00047
00048 #include <config.h>
00049 #include <config-acl.h>
00050 extern "C" {
00051 #include <pwd.h>
00052 #include <grp.h>
00053 #include <time.h>
00054 #include <sys/stat.h>
00055 #include <sys/types.h>
00056 }
00057 #include <unistd.h>
00058 #include <errno.h>
00059 #include <assert.h>
00060 #include <algorithm>
00061 #include <functional>
00062
00063 #include <QtCore/QFile>
00064 #include <QtCore/QDir>
00065 #include <QtGui/QLabel>
00066 #include <QtGui/QPushButton>
00067 #include <QtGui/QCheckBox>
00068 #include <QtCore/QMutableStringListIterator>
00069 #include <QtCore/QTextIStream>
00070 #include <QtGui/QPainter>
00071 #include <QtGui/QLayout>
00072 #include <QtGui/QStyle>
00073 #include <QtGui/QProgressBar>
00074 #include <QVector>
00075 #include <QFileInfo>
00076
00077 #ifdef HAVE_POSIX_ACL
00078 extern "C" {
00079 # include <sys/xattr.h>
00080 }
00081 #endif
00082
00083 #include <kauthorized.h>
00084 #include <kdialog.h>
00085 #include <kdirwatch.h>
00086 #include <kdirnotify.h>
00087 #include <kdiskfreespaceinfo.h>
00088 #include <kdebug.h>
00089 #include <kdesktopfile.h>
00090 #include <kicondialog.h>
00091 #include <kurl.h>
00092 #include <kurlrequester.h>
00093 #include <klocale.h>
00094 #include <kglobal.h>
00095 #include <kglobalsettings.h>
00096 #include <kstandarddirs.h>
00097 #include <kjobuidelegate.h>
00098 #include <kio/job.h>
00099 #include <kio/copyjob.h>
00100 #include <kio/chmodjob.h>
00101 #include <kio/directorysizejob.h>
00102 #include <kio/renamedialog.h>
00103 #include <kio/netaccess.h>
00104 #include <kio/jobuidelegate.h>
00105 #include <kfiledialog.h>
00106 #include <kmimetype.h>
00107 #include <kmountpoint.h>
00108 #include <kiconloader.h>
00109 #include <kmessagebox.h>
00110 #include <kservice.h>
00111 #include <kcombobox.h>
00112 #include <kcompletion.h>
00113 #include <klineedit.h>
00114 #include <kseparator.h>
00115 #include <ksqueezedtextlabel.h>
00116 #include <klibloader.h>
00117 #include <kmimetypetrader.h>
00118 #include <kmetaprops.h>
00119 #include <kpreviewprops.h>
00120 #include <krun.h>
00121 #include <kvbox.h>
00122 #include <kacl.h>
00123 #include <kconfiggroup.h>
00124 #include <kshell.h>
00125 #include <kcapacitybar.h>
00126 #include <kfileitemlistproperties.h>
00127
00128 #ifndef Q_OS_WIN
00129 #include "kfilesharedialog.h"
00130 #endif
00131
00132 #include "ui_kpropertiesdesktopbase.h"
00133 #include "ui_kpropertiesdesktopadvbase.h"
00134 #ifdef HAVE_POSIX_ACL
00135 #include "kacleditwidget.h"
00136 #endif
00137
00138 #include <kbuildsycocaprogressdialog.h>
00139 #include <kmimetypechooser.h>
00140
00141 #ifdef Q_WS_WIN
00142 # include <kkernel_win.h>
00143 #ifdef __GNUC__
00144 # warning TODO: port completely to win32
00145 #endif
00146 #endif
00147
00148 using namespace KDEPrivate;
00149
00150 static QString nameFromFileName(QString nameStr)
00151 {
00152 if ( nameStr.endsWith(".desktop") )
00153 nameStr.truncate( nameStr.length() - 8 );
00154 if ( nameStr.endsWith(".kdelnk") )
00155 nameStr.truncate( nameStr.length() - 7 );
00156
00157 nameStr = KIO::decodeFileName( nameStr );
00158 return nameStr;
00159 }
00160
00161 mode_t KFilePermissionsPropsPlugin::fperm[3][4] = {
00162 {S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID},
00163 {S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID},
00164 {S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX}
00165 };
00166
00167 class KPropertiesDialog::KPropertiesDialogPrivate
00168 {
00169 public:
00170 KPropertiesDialogPrivate(KPropertiesDialog *qq)
00171 {
00172 q = qq;
00173 m_aborted = false;
00174 fileSharePage = 0;
00175 }
00176 ~KPropertiesDialogPrivate()
00177 {
00178 }
00179
00183 void init();
00187 void insertPages();
00188
00189 KPropertiesDialog *q;
00190 bool m_aborted:1;
00191 QWidget* fileSharePage;
00195 KUrl m_singleUrl;
00199 KFileItemList m_items;
00203 QString m_defaultName;
00204 KUrl m_currentDir;
00208 QList<KPropertiesDialogPlugin*> m_pageList;
00209 };
00210
00211 KPropertiesDialog::KPropertiesDialog (const KFileItem& item,
00212 QWidget* parent)
00213 : KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
00214 {
00215 setCaption( i18n( "Properties for %1" , KIO::decodeFileName(item.url().fileName())) );
00216
00217 assert( !item.isNull() );
00218 d->m_items.append(item);
00219
00220 d->m_singleUrl = item.url();
00221 assert(!d->m_singleUrl.isEmpty());
00222
00223 d->init();
00224 }
00225
00226 KPropertiesDialog::KPropertiesDialog (const QString& title,
00227 QWidget* parent)
00228 : KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
00229 {
00230 setCaption( i18n( "Properties for %1", title ) );
00231
00232 d->init();
00233 }
00234
00235 KPropertiesDialog::KPropertiesDialog(const KFileItemList& _items,
00236 QWidget* parent)
00237 : KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
00238 {
00239 if ( _items.count() > 1 )
00240 setCaption( i18np( "Properties for 1 item", "Properties for %1 Selected Items", _items.count() ) );
00241 else
00242 setCaption( i18n( "Properties for %1" , KIO::decodeFileName(_items.first().url().fileName())) );
00243
00244 assert( !_items.isEmpty() );
00245 d->m_singleUrl = _items.first().url();
00246 assert(!d->m_singleUrl.isEmpty());
00247
00248 d->m_items = _items;
00249
00250 d->init();
00251 }
00252
00253 KPropertiesDialog::KPropertiesDialog (const KUrl& _url,
00254 QWidget* parent)
00255 : KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
00256 {
00257 setCaption( i18n( "Properties for %1" , KIO::decodeFileName(_url.fileName())) );
00258
00259 d->m_singleUrl = _url;
00260
00261 KIO::UDSEntry entry;
00262 KIO::NetAccess::stat(_url, entry, parent);
00263
00264 d->m_items.append(KFileItem(entry, _url));
00265 d->init();
00266 }
00267
00268 KPropertiesDialog::KPropertiesDialog (const KUrl& _tempUrl, const KUrl& _currentDir,
00269 const QString& _defaultName,
00270 QWidget* parent)
00271 : KPageDialog(parent), d(new KPropertiesDialogPrivate(this))
00272 {
00273 setCaption( i18n( "Properties for %1" , KIO::decodeFileName(_tempUrl.fileName())) );
00274
00275 d->m_singleUrl = _tempUrl;
00276 d->m_defaultName = _defaultName;
00277 d->m_currentDir = _currentDir;
00278 assert(!d->m_singleUrl.isEmpty());
00279
00280
00281 d->m_items.append(KFileItem(KFileItem::Unknown, KFileItem::Unknown, d->m_singleUrl));
00282 d->init();
00283 }
00284
00285 bool KPropertiesDialog::showDialog(const KFileItem& item, QWidget* parent,
00286 bool modal)
00287 {
00288
00289
00290 #ifdef Q_WS_WIN
00291 QString localPath = item.localPath();
00292 if (!localPath.isEmpty())
00293 return showWin32FilePropertyDialog(localPath);
00294 #endif
00295 KPropertiesDialog* dlg = new KPropertiesDialog(item, parent);
00296 if (modal) {
00297 dlg->exec();
00298 } else {
00299 dlg->show();
00300 }
00301
00302 return true;
00303 }
00304
00305 bool KPropertiesDialog::showDialog(const KUrl& _url, QWidget* parent,
00306 bool modal)
00307 {
00308 #ifdef Q_WS_WIN
00309 if (_url.isLocalFile())
00310 return showWin32FilePropertyDialog( _url.toLocalFile() );
00311 #endif
00312 KPropertiesDialog* dlg = new KPropertiesDialog(_url, parent);
00313 if (modal) {
00314 dlg->exec();
00315 } else {
00316 dlg->show();
00317 }
00318
00319 return true;
00320 }
00321
00322 bool KPropertiesDialog::showDialog(const KFileItemList& _items, QWidget* parent,
00323 bool modal)
00324 {
00325 if (_items.count()==1) {
00326 const KFileItem item = _items.first();
00327 if (item.entry().count() == 0 && item.localPath().isEmpty())
00328
00329 return KPropertiesDialog::showDialog(item.url(), parent, modal);
00330 else
00331 return KPropertiesDialog::showDialog(_items.first(), parent, modal);
00332 }
00333 KPropertiesDialog* dlg = new KPropertiesDialog(_items, parent);
00334 if (modal) {
00335 dlg->exec();
00336 } else {
00337 dlg->show();
00338 }
00339 return true;
00340 }
00341
00342 void KPropertiesDialog::KPropertiesDialogPrivate::init()
00343 {
00344 q->setFaceType(KPageDialog::Tabbed);
00345 q->setButtons(KDialog::Ok | KDialog::Cancel);
00346 q->setDefaultButton(KDialog::Ok);
00347
00348 connect(q, SIGNAL(okClicked()), q, SLOT(slotOk()));
00349 connect(q, SIGNAL(cancelClicked()), q, SLOT(slotCancel()));
00350
00351 insertPages();
00352
00353 KConfigGroup group(KGlobal::config(), "KPropertiesDialog");
00354 q->restoreDialogSize(group);
00355 }
00356
00357 void KPropertiesDialog::showFileSharingPage()
00358 {
00359 if (d->fileSharePage) {
00360
00361
00362 }
00363 }
00364
00365 void KPropertiesDialog::setFileSharingPage(QWidget* page) {
00366 d->fileSharePage = page;
00367 }
00368
00369
00370 void KPropertiesDialog::setFileNameReadOnly( bool ro )
00371 {
00372 foreach(KPropertiesDialogPlugin *it, d->m_pageList) {
00373 KFilePropsPlugin* plugin = dynamic_cast<KFilePropsPlugin*>(it);
00374 if ( plugin ) {
00375 plugin->setFileNameReadOnly( ro );
00376 break;
00377 }
00378 }
00379 }
00380
00381 KPropertiesDialog::~KPropertiesDialog()
00382 {
00383 qDeleteAll(d->m_pageList);
00384 delete d;
00385
00386 KConfigGroup group(KGlobal::config(), "KPropertiesDialog");
00387 saveDialogSize(group, KConfigBase::Persistent);
00388 }
00389
00390 void KPropertiesDialog::insertPlugin (KPropertiesDialogPlugin* plugin)
00391 {
00392 connect (plugin, SIGNAL (changed ()),
00393 plugin, SLOT (setDirty ()));
00394
00395 d->m_pageList.append(plugin);
00396 }
00397
00398 KUrl KPropertiesDialog::kurl() const
00399 {
00400 return d->m_singleUrl;
00401 }
00402
00403 KFileItem& KPropertiesDialog::item()
00404 {
00405 return d->m_items.first();
00406 }
00407
00408 KFileItemList KPropertiesDialog::items() const
00409 {
00410 return d->m_items;
00411 }
00412
00413 KUrl KPropertiesDialog::currentDir() const
00414 {
00415 return d->m_currentDir;
00416 }
00417
00418 QString KPropertiesDialog::defaultName() const
00419 {
00420 return d->m_defaultName;
00421 }
00422
00423 bool KPropertiesDialog::canDisplay( const KFileItemList& _items )
00424 {
00425
00426 return KFilePropsPlugin::supports( _items ) ||
00427 KFilePermissionsPropsPlugin::supports( _items ) ||
00428 KDesktopPropsPlugin::supports( _items ) ||
00429 KUrlPropsPlugin::supports( _items ) ||
00430 KDevicePropsPlugin::supports( _items ) ||
00431 KFileMetaPropsPlugin::supports( _items ) ||
00432 KPreviewPropsPlugin::supports( _items );
00433 }
00434
00435 void KPropertiesDialog::slotOk()
00436 {
00437 QList<KPropertiesDialogPlugin*>::const_iterator pageListIt;
00438 d->m_aborted = false;
00439
00440 KFilePropsPlugin * filePropsPlugin = 0L;
00441 if (qobject_cast<KFilePropsPlugin*>(d->m_pageList.first()))
00442 filePropsPlugin = static_cast<KFilePropsPlugin *>(d->m_pageList.first());
00443
00444
00445
00446
00447 for (pageListIt = d->m_pageList.constBegin(); pageListIt != d->m_pageList.constEnd(); ++pageListIt) {
00448 if ( (*pageListIt)->isDirty() && filePropsPlugin )
00449 {
00450 filePropsPlugin->setDirty();
00451 break;
00452 }
00453 }
00454
00455
00456
00457
00458
00459 for (pageListIt = d->m_pageList.constBegin(); pageListIt != d->m_pageList.constEnd() && !d->m_aborted; ++pageListIt) {
00460 if ( (*pageListIt)->isDirty() )
00461 {
00462 kDebug( 250 ) << "applying changes for " << (*pageListIt)->metaObject()->className();
00463 (*pageListIt)->applyChanges();
00464
00465 }
00466 else {
00467 kDebug( 250 ) << "skipping page " << (*pageListIt)->metaObject()->className();
00468 }
00469 }
00470
00471 if ( !d->m_aborted && filePropsPlugin )
00472 filePropsPlugin->postApplyChanges();
00473
00474 if ( !d->m_aborted )
00475 {
00476 emit applied();
00477 emit propertiesClosed();
00478 deleteLater();
00479 accept();
00480 }
00481 }
00482
00483 void KPropertiesDialog::slotCancel()
00484 {
00485 emit canceled();
00486 emit propertiesClosed();
00487
00488 deleteLater();
00489 done( Rejected );
00490 }
00491
00492 void KPropertiesDialog::KPropertiesDialogPrivate::insertPages()
00493 {
00494 if (m_items.isEmpty())
00495 return;
00496
00497 if ( KFilePropsPlugin::supports( m_items ) ) {
00498 KPropertiesDialogPlugin *p = new KFilePropsPlugin(q);
00499 q->insertPlugin(p);
00500 }
00501
00502 if ( KFilePermissionsPropsPlugin::supports( m_items ) ) {
00503 KPropertiesDialogPlugin *p = new KFilePermissionsPropsPlugin(q);
00504 q->insertPlugin(p);
00505 }
00506
00507 if ( KDesktopPropsPlugin::supports( m_items ) ) {
00508 KPropertiesDialogPlugin *p = new KDesktopPropsPlugin(q);
00509 q->insertPlugin(p);
00510 }
00511
00512 if ( KUrlPropsPlugin::supports( m_items ) ) {
00513 KPropertiesDialogPlugin *p = new KUrlPropsPlugin(q);
00514 q->insertPlugin(p);
00515 }
00516
00517 if ( KDevicePropsPlugin::supports( m_items ) ) {
00518 KPropertiesDialogPlugin *p = new KDevicePropsPlugin(q);
00519 q->insertPlugin(p);
00520 }
00521
00522 if ( KFileMetaPropsPlugin::supports( m_items ) ) {
00523 KPropertiesDialogPlugin *p = new KFileMetaPropsPlugin(q);
00524 q->insertPlugin(p);
00525 }
00526
00527 if ( KPreviewPropsPlugin::supports( m_items ) ) {
00528 KPropertiesDialogPlugin *p = new KPreviewPropsPlugin(q);
00529 q->insertPlugin(p);
00530 }
00531
00532 #ifndef Q_OS_WIN
00533 if ( KAuthorized::authorizeKAction("sharefile") &&
00534 KFileSharePropsPlugin::supports( m_items ) ) {
00535 KPropertiesDialogPlugin *p = new KFileSharePropsPlugin(q);
00536 q->insertPlugin(p);
00537 }
00538 #endif
00539
00540
00541
00542 if ( m_items.count() != 1 )
00543 return;
00544
00545 const KFileItem item = m_items.first();
00546 const QString mimetype = item.mimetype();
00547
00548 if ( mimetype.isEmpty() )
00549 return;
00550
00551 QString query = QString::fromLatin1(
00552 "((not exist [X-KDE-Protocol]) or "
00553 " ([X-KDE-Protocol] == '%1' ) )"
00554 ).arg(item.url().protocol());
00555
00556 kDebug( 250 ) << "trader query: " << query;
00557 KService::List offers = KMimeTypeTrader::self()->query( mimetype, "KPropertiesDialog/Plugin", query );
00558 foreach (const KService::Ptr &ptr, offers) {
00559 KPropertiesDialogPlugin *plugin = ptr->createInstance<KPropertiesDialogPlugin>(q);
00560 if (!plugin)
00561 continue;
00562 plugin->setObjectName(ptr->name());
00563
00564 q->insertPlugin(plugin);
00565 }
00566 }
00567
00568 void KPropertiesDialog::updateUrl( const KUrl& _newUrl )
00569 {
00570 Q_ASSERT(d->m_items.count() == 1);
00571 kDebug(250) << "KPropertiesDialog::updateUrl (pre)" << _newUrl.url();
00572 KUrl newUrl = _newUrl;
00573 emit saveAs(d->m_singleUrl, newUrl);
00574 kDebug(250) << "KPropertiesDialog::updateUrl (post)" << newUrl.url();
00575
00576 d->m_singleUrl = newUrl;
00577 d->m_items.first().setUrl(newUrl);
00578 assert(!d->m_singleUrl.isEmpty());
00579
00580
00581 foreach (KPropertiesDialogPlugin *it, d->m_pageList) {
00582 if ( qobject_cast<KUrlPropsPlugin*>(it) ||
00583 qobject_cast<KDesktopPropsPlugin*>(it) )
00584 {
00585
00586 it->setDirty();
00587 break;
00588 }
00589 }
00590 }
00591
00592 void KPropertiesDialog::rename( const QString& _name )
00593 {
00594 Q_ASSERT(d->m_items.count() == 1);
00595 kDebug(250) << "KPropertiesDialog::rename " << _name;
00596 KUrl newUrl;
00597
00598 if (!d->m_currentDir.isEmpty()) {
00599 newUrl = d->m_currentDir;
00600 newUrl.addPath(_name);
00601 } else {
00602 QString tmpurl = d->m_singleUrl.url();
00603 if (!tmpurl.isEmpty() && tmpurl.at(tmpurl.length() - 1) == '/') {
00604
00605 tmpurl.truncate(tmpurl.length() - 1);
00606 }
00607
00608 newUrl = tmpurl;
00609 newUrl.setFileName(_name);
00610 }
00611 updateUrl(newUrl);
00612 }
00613
00614 void KPropertiesDialog::abortApplying()
00615 {
00616 d->m_aborted = true;
00617 }
00618
00619 class KPropertiesDialogPlugin::KPropertiesDialogPluginPrivate
00620 {
00621 public:
00622 KPropertiesDialogPluginPrivate()
00623 {
00624 }
00625 ~KPropertiesDialogPluginPrivate()
00626 {
00627 }
00628
00629 bool m_bDirty;
00630 int fontHeight;
00631 };
00632
00633 KPropertiesDialogPlugin::KPropertiesDialogPlugin( KPropertiesDialog *_props )
00634 : QObject( _props ),d(new KPropertiesDialogPluginPrivate)
00635 {
00636 properties = _props;
00637 d->fontHeight = 2*properties->fontMetrics().height();
00638 d->m_bDirty = false;
00639 }
00640
00641 KPropertiesDialogPlugin::~KPropertiesDialogPlugin()
00642 {
00643 delete d;
00644 }
00645
00646 bool KPropertiesDialogPlugin::isDesktopFile( const KFileItem& _item )
00647 {
00648 return _item.isDesktopFile();
00649 }
00650
00651 void KPropertiesDialogPlugin::setDirty( bool b )
00652 {
00653 d->m_bDirty = b;
00654 }
00655
00656 void KPropertiesDialogPlugin::setDirty()
00657 {
00658 d->m_bDirty = true;
00659 }
00660
00661 bool KPropertiesDialogPlugin::isDirty() const
00662 {
00663 return d->m_bDirty;
00664 }
00665
00666 void KPropertiesDialogPlugin::applyChanges()
00667 {
00668 kWarning(250) << "applyChanges() not implemented in page !";
00669 }
00670
00671 int KPropertiesDialogPlugin::fontHeight() const
00672 {
00673 return d->fontHeight;
00674 }
00675
00677
00678 class KFilePropsPlugin::KFilePropsPluginPrivate
00679 {
00680 public:
00681 KFilePropsPluginPrivate()
00682 {
00683 dirSizeJob = 0L;
00684 dirSizeUpdateTimer = 0L;
00685 m_lined = 0;
00686 m_capacityBar = 0;
00687 m_linkTargetLineEdit = 0;
00688 }
00689 ~KFilePropsPluginPrivate()
00690 {
00691 if ( dirSizeJob )
00692 dirSizeJob->kill();
00693 }
00694
00695 KIO::DirectorySizeJob * dirSizeJob;
00696 QTimer *dirSizeUpdateTimer;
00697 QFrame *m_frame;
00698 bool bMultiple;
00699 bool bIconChanged;
00700 bool bKDesktopMode;
00701 bool bDesktopFile;
00702 KCapacityBar *m_capacityBar;
00703 QString mimeType;
00704 QString oldFileName;
00705 KLineEdit* m_lined;
00706
00707 QWidget *iconArea;
00708 QWidget *nameArea;
00709
00710 QLabel *m_sizeLabel;
00711 QPushButton *m_sizeDetermineButton;
00712 QPushButton *m_sizeStopButton;
00713 KLineEdit* m_linkTargetLineEdit;
00714
00715 QString m_sRelativePath;
00716 bool m_bFromTemplate;
00717
00721 QString oldName;
00722 };
00723
00724 KFilePropsPlugin::KFilePropsPlugin( KPropertiesDialog *_props )
00725 : KPropertiesDialogPlugin( _props ),d(new KFilePropsPluginPrivate)
00726 {
00727 d->bMultiple = (properties->items().count() > 1);
00728 d->bIconChanged = false;
00729 d->bKDesktopMode = (qApp->objectName() == "kdesktop");
00730 d->bDesktopFile = KDesktopPropsPlugin::supports(properties->items());
00731 kDebug(250) << "KFilePropsPlugin::KFilePropsPlugin bMultiple=" << d->bMultiple;
00732
00733
00734
00735 bool isLocal;
00736 const KFileItem item = properties->item();
00737 KUrl url = item.mostLocalUrl( isLocal );
00738 bool isReallyLocal = item.url().isLocalFile();
00739 bool bDesktopFile = item.isDesktopFile();
00740 mode_t mode = item.mode();
00741 bool hasDirs = item.isDir() && !item.isLink();
00742 bool hasRoot = url.path() == QLatin1String("/");
00743 QString iconStr = KMimeType::iconNameForUrl(url, mode);
00744 QString directory = properties->kurl().directory();
00745 QString protocol = properties->kurl().protocol();
00746 QString mimeComment = item.mimeComment();
00747 d->mimeType = item.mimetype();
00748 KIO::filesize_t totalSize = item.size();
00749 QString magicMimeComment;
00750 if ( isLocal ) {
00751 KMimeType::Ptr magicMimeType = KMimeType::findByFileContent( url.path() );
00752 if ( magicMimeType->name() != KMimeType::defaultMimeType() )
00753 magicMimeComment = magicMimeType->comment();
00754 }
00755 #ifdef Q_WS_WIN
00756 if ( isReallyLocal ) {
00757 directory = QDir::toNativeSeparators( directory.mid( 1 ) );
00758 }
00759 #endif
00760
00761
00762 QString filename;
00763 bool isTrash = false;
00764 bool isDevice = false;
00765 d->m_bFromTemplate = false;
00766
00767
00768 uint iDirCount = hasDirs ? 1 : 0;
00769 uint iFileCount = 1-iDirCount;
00770
00771 d->m_frame = new QFrame();
00772 properties->addPage(d->m_frame, i18nc("@title:tab File properties", "&General"));
00773
00774 QVBoxLayout *vbl = new QVBoxLayout( d->m_frame );
00775 vbl->setMargin( 0 );
00776 vbl->setObjectName( QLatin1String( "vbl" ) );
00777 QGridLayout *grid = new QGridLayout();
00778 grid->setColumnStretch(0, 0);
00779 grid->setColumnStretch(1, 0);
00780 grid->setColumnStretch(2, 1);
00781 grid->addItem(new QSpacerItem(KDialog::spacingHint(),0), 0, 1);
00782 vbl->addLayout(grid);
00783 int curRow = 0;
00784
00785 if ( !d->bMultiple )
00786 {
00787 QString path;
00788 if ( !d->m_bFromTemplate ) {
00789 isTrash = ( properties->kurl().protocol().toLower() == "trash" );
00790 isDevice = ( properties->kurl().protocol().toLower() == "device" );
00791
00792 if ( isReallyLocal )
00793 path = properties->kurl().toLocalFile();
00794 else
00795 path = properties->kurl().prettyUrl();
00796 } else {
00797 path = properties->currentDir().path(KUrl::AddTrailingSlash) + properties->defaultName();
00798 directory = properties->currentDir().prettyUrl();
00799 }
00800
00801 if (d->bDesktopFile) {
00802 determineRelativePath( path );
00803 }
00804
00805
00806 filename = properties->defaultName();
00807 if ( filename.isEmpty() ) {
00808 filename = item.name();
00809 } else {
00810 d->m_bFromTemplate = true;
00811 setDirty();
00812 }
00813 d->oldFileName = filename;
00814
00815
00816 filename = nameFromFileName( filename );
00817
00818 if ( d->bKDesktopMode && d->bDesktopFile ) {
00819 KDesktopFile config( url.path() );
00820 if ( config.desktopGroup().hasKey( "Name" ) ) {
00821 filename = config.readName();
00822 }
00823 }
00824
00825 d->oldName = filename;
00826 }
00827 else
00828 {
00829
00830 const KFileItemList items = properties->items();
00831 KFileItemList::const_iterator kit = items.begin();
00832 const KFileItemList::const_iterator kend = items.end();
00833 for ( ++kit ; kit != kend; ++kit )
00834 {
00835 const KUrl url = (*kit).url();
00836 kDebug(250) << "KFilePropsPlugin::KFilePropsPlugin " << url.prettyUrl();
00837
00838
00839 if ( url.isLocalFile() != isLocal )
00840 isLocal = false;
00841 if ( bDesktopFile && (*kit).isDesktopFile() != bDesktopFile )
00842 bDesktopFile = false;
00843 if ( (*kit).mode() != mode )
00844 mode = (mode_t)0;
00845 if ( KMimeType::iconNameForUrl(url, mode) != iconStr )
00846 iconStr = "document-multiple";
00847 if ( url.directory() != directory )
00848 directory.clear();
00849 if ( url.protocol() != protocol )
00850 protocol.clear();
00851 if ( !mimeComment.isNull() && (*kit).mimeComment() != mimeComment )
00852 mimeComment.clear();
00853 if ( isLocal && !magicMimeComment.isNull() ) {
00854 KMimeType::Ptr magicMimeType = KMimeType::findByFileContent( url.path() );
00855 if ( magicMimeType->comment() != magicMimeComment )
00856 magicMimeComment.clear();
00857 }
00858
00859 if ( isLocal && url.path() == QLatin1String("/") )
00860 hasRoot = true;
00861 if ( (*kit).isDir() && !(*kit).isLink() )
00862 {
00863 iDirCount++;
00864 hasDirs = true;
00865 }
00866 else
00867 {
00868 iFileCount++;
00869 totalSize += (*kit).size();
00870 }
00871 }
00872 }
00873
00874 if (!isReallyLocal && !protocol.isEmpty())
00875 {
00876 directory += ' ';
00877 directory += '(';
00878 directory += protocol;
00879 directory += ')';
00880 }
00881
00882 if ( !isDevice && !isTrash && (bDesktopFile || S_ISDIR(mode)) && !d->bMultiple )
00883 {
00884 KIconButton *iconButton = new KIconButton( d->m_frame );
00885 int bsize = 66 + 2 * iconButton->style()->pixelMetric(QStyle::PM_ButtonMargin);
00886 iconButton->setFixedSize(bsize, bsize);
00887 iconButton->setIconSize(48);
00888 iconButton->setStrictIconSize(false);
00889
00890
00891 QString iconStr = KMimeType::findByUrl( url, mode )->iconName( url );
00892 if ( bDesktopFile && isLocal )
00893 {
00894 KDesktopFile config( url.path() );
00895 KConfigGroup group = config.desktopGroup();
00896 iconStr = group.readEntry( "Icon" );
00897 if ( config.hasDeviceType() )
00898 iconButton->setIconType( KIconLoader::Desktop, KIconLoader::Device );
00899 else
00900 iconButton->setIconType( KIconLoader::Desktop, KIconLoader::Application );
00901 } else
00902 iconButton->setIconType( KIconLoader::Desktop, KIconLoader::Place );
00903 iconButton->setIcon(iconStr);
00904 d->iconArea = iconButton;
00905 connect( iconButton, SIGNAL( iconChanged(const QString&) ),
00906 this, SLOT( slotIconChanged() ) );
00907 } else {
00908 QLabel *iconLabel = new QLabel( d->m_frame );
00909 int bsize = 66 + 2 * iconLabel->style()->pixelMetric(QStyle::PM_ButtonMargin);
00910 iconLabel->setFixedSize(bsize, bsize);
00911 iconLabel->setPixmap( KIconLoader::global()->loadIcon( iconStr, KIconLoader::Desktop, 48) );
00912 d->iconArea = iconLabel;
00913 }
00914 grid->addWidget(d->iconArea, curRow, 0, Qt::AlignLeft);
00915
00916 if (d->bMultiple || isTrash || isDevice || hasRoot)
00917 {
00918 QLabel *lab = new QLabel(d->m_frame );
00919 if ( d->bMultiple )
00920 lab->setText( KIO::itemsSummaryString( iFileCount + iDirCount, iFileCount, iDirCount, 0, false ) );
00921 else
00922 lab->setText( filename );
00923 d->nameArea = lab;
00924 } else
00925 {
00926 d->m_lined = new KLineEdit( d->m_frame );
00927 d->m_lined->setText(filename);
00928 d->nameArea = d->m_lined;
00929 d->m_lined->setFocus();
00930
00931
00932 KFileItemListProperties itemList(KFileItemList()<< item);
00933 setFileNameReadOnly(!itemList.supportsMoving());
00934
00935
00936 QString extension = KMimeType::extractKnownExtension( filename );
00937 if ( !extension.isEmpty() )
00938 d->m_lined->setSelection( 0, filename.length() - extension.length() - 1 );
00939 else
00940 {
00941 int lastDot = filename.lastIndexOf('.');
00942 if (lastDot > 0)
00943 d->m_lined->setSelection(0, lastDot);
00944 }
00945
00946 connect( d->m_lined, SIGNAL( textChanged( const QString & ) ),
00947 this, SLOT( nameFileChanged(const QString & ) ) );
00948 }
00949
00950 grid->addWidget(d->nameArea, curRow++, 2);
00951
00952 KSeparator* sep = new KSeparator( Qt::Horizontal, d->m_frame);
00953 grid->addWidget(sep, curRow, 0, 1, 3);
00954 ++curRow;
00955
00956 QLabel *l;
00957 if ( !mimeComment.isEmpty() && !isDevice && !isTrash)
00958 {
00959 l = new QLabel(i18n("Type:"), d->m_frame );
00960
00961 grid->addWidget(l, curRow, 0, Qt::AlignRight);
00962
00963 KHBox *box = new KHBox(d->m_frame);
00964 box->setSpacing(20);
00965 l = new QLabel(mimeComment, box );
00966
00967 #ifdef Q_WS_X11
00968
00969 QPushButton *button = new QPushButton(box);
00970
00971 button->setIcon( KIcon(QString::fromLatin1("configure")) );
00972 const int pixmapSize = button->style()->pixelMetric(QStyle::PM_SmallIconSize);
00973 button->setFixedSize( pixmapSize+8, pixmapSize+8 );
00974 if ( d->mimeType == KMimeType::defaultMimeType() )
00975 button->setToolTip(i18n("Create new file type"));
00976 else
00977 button->setToolTip(i18n("Edit file type"));
00978
00979 connect( button, SIGNAL( clicked() ), SLOT( slotEditFileType() ));
00980
00981 if (!KAuthorized::authorizeKAction("editfiletype"))
00982 button->hide();
00983 #endif
00984
00985 grid->addWidget(box, curRow++, 2);
00986 }
00987
00988 if ( !magicMimeComment.isEmpty() && magicMimeComment != mimeComment )
00989 {
00990 l = new QLabel(i18n("Contents:"), d->m_frame );
00991 grid->addWidget(l, curRow, 0, Qt::AlignRight);
00992
00993 l = new QLabel(magicMimeComment, d->m_frame );
00994 grid->addWidget(l, curRow++, 2);
00995 }
00996
00997 if ( !directory.isEmpty() )
00998 {
00999 l = new QLabel( i18n("Location:"), d->m_frame );
01000 grid->addWidget(l, curRow, 0, Qt::AlignRight);
01001
01002 l = new KSqueezedTextLabel( directory, d->m_frame );
01003
01004 l->setLayoutDirection(Qt::LeftToRight);
01005
01006
01007 if (properties->layoutDirection() == Qt::RightToLeft)
01008 l->setAlignment( Qt::AlignRight );
01009 l->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
01010 grid->addWidget(l, curRow++, 2);
01011 }
01012
01013 l = new QLabel(i18n("Size:"), d->m_frame );
01014 grid->addWidget(l, curRow, 0, Qt::AlignRight);
01015
01016 d->m_sizeLabel = new QLabel( d->m_frame );
01017 grid->addWidget( d->m_sizeLabel, curRow++, 2 );
01018
01019 if ( !hasDirs )
01020 {
01021 d->m_sizeLabel->setText(QString::fromLatin1("%1 (%2)").arg(KIO::convertSize(totalSize))
01022 .arg(KGlobal::locale()->formatNumber(totalSize, 0)));
01023 d->m_sizeDetermineButton = 0L;
01024 d->m_sizeStopButton = 0L;
01025 }
01026 else
01027 {
01028 QHBoxLayout * sizelay = new QHBoxLayout();
01029 grid->addLayout( sizelay, curRow++, 2 );
01030
01031
01032 d->m_sizeDetermineButton = new QPushButton( i18n("Calculate"), d->m_frame );
01033 d->m_sizeStopButton = new QPushButton( i18n("Stop"), d->m_frame );
01034 connect( d->m_sizeDetermineButton, SIGNAL( clicked() ), this, SLOT( slotSizeDetermine() ) );
01035 connect( d->m_sizeStopButton, SIGNAL( clicked() ), this, SLOT( slotSizeStop() ) );
01036 sizelay->addWidget(d->m_sizeDetermineButton, 0);
01037 sizelay->addWidget(d->m_sizeStopButton, 0);
01038 sizelay->addStretch(10);
01039
01040
01041 if ( isLocal && !hasRoot )
01042 {
01043 d->m_sizeDetermineButton->setText( i18n("Refresh") );
01044 slotSizeDetermine();
01045 }
01046 else
01047 d->m_sizeStopButton->setEnabled( false );
01048 }
01049
01050 if (!d->bMultiple && item.isLink()) {
01051 l = new QLabel(i18n("Points to:"), d->m_frame );
01052 grid->addWidget(l, curRow, 0, Qt::AlignRight);
01053
01054 d->m_linkTargetLineEdit = new KLineEdit(item.linkDest(), d->m_frame );
01055 grid->addWidget(d->m_linkTargetLineEdit, curRow++, 2);
01056 }
01057
01058 if (!d->bMultiple)
01059 {
01060 KDateTime dt = item.time(KFileItem::CreationTime);
01061 if ( !dt.isNull() )
01062 {
01063 l = new QLabel(i18n("Created:"), d->m_frame );
01064 grid->addWidget(l, curRow, 0, Qt::AlignRight);
01065
01066 l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
01067 grid->addWidget(l, curRow++, 2);
01068 }
01069
01070 dt = item.time(KFileItem::ModificationTime);
01071 if ( !dt.isNull() )
01072 {
01073 l = new QLabel(i18n("Modified:"), d->m_frame );
01074 grid->addWidget(l, curRow, 0, Qt::AlignRight);
01075
01076 l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
01077 grid->addWidget(l, curRow++, 2);
01078 }
01079
01080 dt = item.time(KFileItem::AccessTime);
01081 if ( !dt.isNull() )
01082 {
01083 l = new QLabel(i18n("Accessed:"), d->m_frame );
01084 grid->addWidget(l, curRow, 0, Qt::AlignRight);
01085
01086 l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
01087 grid->addWidget(l, curRow++, 2);
01088 }
01089 }
01090
01091 if ( isLocal && hasDirs )
01092 {
01093
01094 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath( url.path() );
01095 if (mp) {
01096 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( mp->mountPoint() );
01097 if(info.size() != 0 )
01098 {
01099 sep = new KSeparator( Qt::Horizontal, d->m_frame);
01100 grid->addWidget(sep, curRow, 0, 1, 3);
01101 ++curRow;
01102 if (mp->mountPoint() != "/")
01103 {
01104 l = new QLabel(i18n("Mounted on:"), d->m_frame );
01105 grid->addWidget(l, curRow, 0, Qt::AlignRight);
01106
01107 l = new KSqueezedTextLabel( mp->mountPoint(), d->m_frame );
01108 l->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
01109 grid->addWidget( l, curRow++, 2 );
01110 }
01111
01112 l = new QLabel(i18n("Device usage:"), d->m_frame );
01113 grid->addWidget(l, curRow, 0, Qt::AlignRight);
01114
01115 d->m_capacityBar = new KCapacityBar( KCapacityBar::DrawTextOutline, d->m_frame );
01116 grid->addWidget( d->m_capacityBar, curRow++, 2);
01117
01118 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
01119 }
01120 }
01121 }
01122
01123 vbl->addStretch(1);
01124 }
01125
01126
01127
01128
01129
01130
01131 void KFilePropsPlugin::setFileNameReadOnly( bool ro )
01132 {
01133 if ( d->m_lined )
01134 {
01135 d->m_lined->setReadOnly( ro );
01136 if (ro)
01137 {
01138
01139 properties->setButtonFocus(KDialog::Ok);
01140 }
01141 }
01142 }
01143
01144 void KFilePropsPlugin::slotEditFileType()
01145 {
01146 #ifdef Q_WS_X11
01147 QString mime;
01148 if ( d->mimeType == KMimeType::defaultMimeType() ) {
01149 int pos = d->oldFileName.lastIndexOf( '.' );
01150 if ( pos != -1 )
01151 mime = '*' + d->oldFileName.mid(pos);
01152 else
01153 mime = '*';
01154 }
01155 else
01156 mime = d->mimeType;
01157
01158 QString keditfiletype = QString::fromLatin1("keditfiletype");
01159 KRun::runCommand( keditfiletype
01160 + " --parent " + QString::number( (ulong)properties->topLevelWidget()->winId())
01161 + ' ' + KShell::quoteArg(mime),
01162 keditfiletype, keditfiletype , properties->topLevelWidget());
01163 #endif
01164 }
01165
01166 void KFilePropsPlugin::slotIconChanged()
01167 {
01168 d->bIconChanged = true;
01169 emit changed();
01170 }
01171
01172 void KFilePropsPlugin::nameFileChanged(const QString &text )
01173 {
01174 properties->enableButtonOk(!text.isEmpty());
01175 emit changed();
01176 }
01177
01178 void KFilePropsPlugin::determineRelativePath( const QString & path )
01179 {
01180
01181 d->m_sRelativePath = KGlobal::dirs()->relativeLocation("apps", path);
01182 if (d->m_sRelativePath.startsWith('/'))
01183 {
01184 d->m_sRelativePath =KGlobal::dirs()->relativeLocation("xdgdata-apps", path);
01185 if (d->m_sRelativePath.startsWith('/'))
01186 d->m_sRelativePath.clear();
01187 else
01188 d->m_sRelativePath = path;
01189 }
01190 }
01191
01192 void KFilePropsPlugin::slotFoundMountPoint( const QString&,
01193 quint64 kibSize,
01194 quint64 ,
01195 quint64 kibAvail )
01196 {
01197 d->m_capacityBar->setText(
01198 i18nc("Available space out of total partition size (percent used)", "%1 free of %2 (%3% used)",
01199 KIO::convertSizeFromKiB(kibAvail),
01200 KIO::convertSizeFromKiB(kibSize),
01201 100 - (int)(100.0 * kibAvail / kibSize) ));
01202
01203 d->m_capacityBar->setValue(100 - (int)(100.0 * kibAvail / kibSize));
01204 }
01205
01206 void KFilePropsPlugin::slotDirSizeUpdate()
01207 {
01208 KIO::filesize_t totalSize = d->dirSizeJob->totalSize();
01209 KIO::filesize_t totalFiles = d->dirSizeJob->totalFiles();
01210 KIO::filesize_t totalSubdirs = d->dirSizeJob->totalSubdirs();
01211 d->m_sizeLabel->setText(
01212 i18n("Calculating... %1 (%2)\n%3, %4",
01213 KIO::convertSize(totalSize),
01214 totalSize,
01215 i18np("1 file", "%1 files", totalFiles),
01216 i18np("1 sub-folder", "%1 sub-folders", totalSubdirs)));
01217 }
01218
01219 void KFilePropsPlugin::slotDirSizeFinished( KJob * job )
01220 {
01221 if (job->error())
01222 d->m_sizeLabel->setText( job->errorString() );
01223 else
01224 {
01225 KIO::filesize_t totalSize = d->dirSizeJob->totalSize();
01226 KIO::filesize_t totalFiles = d->dirSizeJob->totalFiles();
01227 KIO::filesize_t totalSubdirs = d->dirSizeJob->totalSubdirs();
01228 d->m_sizeLabel->setText( QString::fromLatin1("%1 (%2)\n%3, %4")
01229 .arg(KIO::convertSize(totalSize))
01230 .arg(KGlobal::locale()->formatNumber(totalSize, 0))
01231 .arg(i18np("1 file","%1 files",totalFiles))
01232 .arg(i18np("1 sub-folder","%1 sub-folders",totalSubdirs)));
01233 }
01234 d->m_sizeStopButton->setEnabled(false);
01235
01236 d->m_sizeDetermineButton->setText( i18n("Refresh") );
01237 d->m_sizeDetermineButton->setEnabled(true);
01238 d->dirSizeJob = 0;
01239 delete d->dirSizeUpdateTimer;
01240 d->dirSizeUpdateTimer = 0;
01241 }
01242
01243 void KFilePropsPlugin::slotSizeDetermine()
01244 {
01245 d->m_sizeLabel->setText( i18n("Calculating...") );
01246 kDebug(250) << " KFilePropsPlugin::slotSizeDetermine() properties->item()=" << properties->item();
01247 kDebug(250) << " URL=" << properties->item().url().url();
01248
01249 d->dirSizeJob = KIO::directorySize( properties->items() );
01250 d->dirSizeUpdateTimer = new QTimer(this);
01251 connect( d->dirSizeUpdateTimer, SIGNAL( timeout() ),
01252 SLOT( slotDirSizeUpdate() ) );
01253 d->dirSizeUpdateTimer->start(500);
01254 connect( d->dirSizeJob, SIGNAL( result( KJob * ) ),
01255 SLOT( slotDirSizeFinished( KJob * ) ) );
01256 d->m_sizeStopButton->setEnabled(true);
01257 d->m_sizeDetermineButton->setEnabled(false);
01258
01259
01260 if ( d->m_capacityBar )
01261 {
01262 bool isLocal;
01263 const KFileItem item = properties->item();
01264 KUrl url = item.mostLocalUrl( isLocal );
01265 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath( url.path() );
01266 if (mp) {
01267 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( mp->mountPoint() );
01268 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
01269 }
01270 }
01271 }
01272
01273 void KFilePropsPlugin::slotSizeStop()
01274 {
01275 if ( d->dirSizeJob )
01276 {
01277 KIO::filesize_t totalSize = d->dirSizeJob->totalSize();
01278 d->m_sizeLabel->setText(i18n("At least %1",
01279 KIO::convertSize(totalSize)));
01280 d->dirSizeJob->kill();
01281 d->dirSizeJob = 0;
01282 }
01283 if ( d->dirSizeUpdateTimer )
01284 d->dirSizeUpdateTimer->stop();
01285
01286 d->m_sizeStopButton->setEnabled(false);
01287 d->m_sizeDetermineButton->setEnabled(true);
01288 }
01289
01290 KFilePropsPlugin::~KFilePropsPlugin()
01291 {
01292 delete d;
01293 }
01294
01295 bool KFilePropsPlugin::supports( const KFileItemList& )
01296 {
01297 return true;
01298 }
01299
01300 void KFilePropsPlugin::applyChanges()
01301 {
01302 if ( d->dirSizeJob )
01303 slotSizeStop();
01304
01305 kDebug(250) << "KFilePropsPlugin::applyChanges";
01306
01307 if (qobject_cast<QLineEdit*>(d->nameArea))
01308 {
01309 QString n = ((QLineEdit *) d->nameArea)->text();
01310
01311 while ( ! n.isEmpty() && n[n.length()-1].isSpace() )
01312 n.truncate( n.length() - 1 );
01313 if ( n.isEmpty() )
01314 {
01315 KMessageBox::sorry( properties, i18n("The new file name is empty."));
01316 properties->abortApplying();
01317 return;
01318 }
01319
01320
01321 kDebug(250) << "oldname = " << d->oldName;
01322 kDebug(250) << "newname = " << n;
01323 if ( d->oldName != n || d->m_bFromTemplate ) {
01324 KIO::Job * job = 0L;
01325 KUrl oldurl = properties->kurl();
01326
01327 QString newFileName = KIO::encodeFileName(n);
01328 if (d->bDesktopFile && !newFileName.endsWith(".desktop") && !newFileName.endsWith(".kdelnk"))
01329 newFileName += ".desktop";
01330
01331
01332 properties->rename( newFileName );
01333
01334
01335 if ( !d->m_sRelativePath.isEmpty() )
01336 determineRelativePath( properties->kurl().toLocalFile() );
01337
01338 kDebug(250) << "New URL = " << properties->kurl().url();
01339 kDebug(250) << "old = " << oldurl.url();
01340
01341
01342 if ( !d->m_bFromTemplate )
01343 job = KIO::move( oldurl, properties->kurl() );
01344 else
01345 job = KIO::copy( oldurl, properties->kurl() );
01346
01347 connect( job, SIGNAL( result( KJob * ) ),
01348 SLOT( slotCopyFinished( KJob * ) ) );
01349 connect( job, SIGNAL( renamed( KIO::Job *, const KUrl &, const KUrl & ) ),
01350 SLOT( slotFileRenamed( KIO::Job *, const KUrl &, const KUrl & ) ) );
01351
01352 QEventLoop eventLoop;
01353 connect(this, SIGNAL(leaveModality()),
01354 &eventLoop, SLOT(quit()));
01355 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
01356 return;
01357 }
01358 properties->updateUrl(properties->kurl());
01359
01360 if ( !d->m_sRelativePath.isEmpty() )
01361 determineRelativePath( properties->kurl().toLocalFile() );
01362 }
01363
01364
01365 slotCopyFinished( 0L );
01366 }
01367
01368 void KFilePropsPlugin::slotCopyFinished( KJob * job )
01369 {
01370 kDebug(250) << "KFilePropsPlugin::slotCopyFinished";
01371 if (job)
01372 {
01373
01374 emit leaveModality();
01375 if ( job->error() )
01376 {
01377 job->uiDelegate()->showErrorMessage();
01378
01379 properties->updateUrl( static_cast<KIO::CopyJob*>(job)->srcUrls().first() );
01380 properties->abortApplying();
01381 return;
01382 }
01383 }
01384
01385 assert( !properties->item().isNull() );
01386 assert( !properties->item().url().isEmpty() );
01387
01388
01389 if (d->bDesktopFile && !d->m_sRelativePath.isEmpty())
01390 {
01391 kDebug(250) << "KFilePropsPlugin::slotCopyFinished " << d->m_sRelativePath;
01392 KUrl newURL;
01393 newURL.setPath( KDesktopFile::locateLocal(d->m_sRelativePath) );
01394 kDebug(250) << "KFilePropsPlugin::slotCopyFinished path=" << newURL.path();
01395 properties->updateUrl( newURL );
01396 }
01397
01398 if ( d->bKDesktopMode && d->bDesktopFile ) {
01399
01400 if ( d->oldFileName != properties->kurl().fileName() || d->m_bFromTemplate ) {
01401 KDesktopFile config( properties->kurl().toLocalFile() );
01402 KConfigGroup cg = config.desktopGroup();
01403 QString nameStr = nameFromFileName(properties->kurl().fileName());
01404 cg.writeEntry( "Name", nameStr );
01405 cg.writeEntry( "Name", nameStr, KConfigGroup::Persistent|KConfigGroup::Localized);
01406 }
01407 }
01408
01409 if (d->m_linkTargetLineEdit && !d->bMultiple) {
01410 const KFileItem item = properties->item();
01411 const QString newTarget = d->m_linkTargetLineEdit->text();
01412 if (newTarget != item.linkDest()) {
01413 kDebug(250) << "Updating target of symlink to" << newTarget;
01414 KIO::Job* job = KIO::symlink(newTarget, item.url(), KIO::Overwrite);
01415 job->ui()->setAutoErrorHandlingEnabled(true);
01416 job->exec();
01417 }
01418 }
01419
01420
01421
01422
01423 if ( d->m_bFromTemplate ) {
01424
01425 KDesktopFile templateResult ( static_cast<KIO::CopyJob*>(job)->srcUrls().first().toLocalFile() );
01426 if ( templateResult.hasApplicationType() ) {
01427
01428
01429
01430
01431 KFileItem appLink ( properties->item() );
01432 KFileItemList fileItemList;
01433 fileItemList << appLink;
01434
01435
01436 KIO::Job* chmodJob = KIO::chmod( fileItemList, 0100, 0100, QString(), QString(), KIO::HideProgressInfo );
01437 chmodJob->exec();
01438 }
01439 }
01440 }
01441
01442 void KFilePropsPlugin::applyIconChanges()
01443 {
01444 KIconButton *iconButton = qobject_cast<KIconButton*>(d->iconArea);
01445 if ( !iconButton || !d->bIconChanged )
01446 return;
01447
01448
01449 KUrl url = properties->kurl();
01450 url = KIO::NetAccess::mostLocalUrl( url, properties );
01451 if ( url.isLocalFile()) {
01452 QString path;
01453
01454 if (S_ISDIR(properties->item().mode()))
01455 {
01456 path = url.toLocalFile(KUrl::AddTrailingSlash) + QString::fromLatin1(".directory");
01457
01458
01459 }
01460 else
01461 path = url.toLocalFile();
01462
01463
01464 QString str = KMimeType::findByUrl( url,
01465 properties->item().mode(),
01466 true )->iconName();
01467
01468 QString sIcon;
01469 if ( str != iconButton->icon() )
01470 sIcon = iconButton->icon();
01471
01472
01473 kDebug(250) << "**" << path << "**";
01474 QFile f( path );
01475
01476
01477 if ( !sIcon.isEmpty() || f.exists() )
01478 {
01479 KDesktopFile cfg(path);
01480 kDebug(250) << "sIcon = " << (sIcon);
01481 kDebug(250) << "str = " << (str);
01482 cfg.desktopGroup().writeEntry( "Icon", sIcon );
01483 cfg.sync();
01484
01485 cfg.reparseConfiguration();
01486 if ( cfg.desktopGroup().readEntry("Icon") != sIcon ) {
01487 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not "
01488 "have sufficient access to write to <b>%1</b>.</qt>", path));
01489 }
01490 }
01491 }
01492 }
01493
01494 void KFilePropsPlugin::slotFileRenamed( KIO::Job *, const KUrl &, const KUrl & newUrl )
01495 {
01496
01497
01498 properties->updateUrl( newUrl );
01499 }
01500
01501 void KFilePropsPlugin::postApplyChanges()
01502 {
01503
01504 applyIconChanges();
01505
01506 const KFileItemList items = properties->items();
01507 const KUrl::List lst = items.urlList();
01508 org::kde::KDirNotify::emitFilesChanged( lst.toStringList() );
01509 }
01510
01511 class KFilePermissionsPropsPlugin::KFilePermissionsPropsPluginPrivate
01512 {
01513 public:
01514 KFilePermissionsPropsPluginPrivate()
01515 {
01516 }
01517 ~KFilePermissionsPropsPluginPrivate()
01518 {
01519 }
01520
01521 QFrame *m_frame;
01522 QCheckBox *cbRecursive;
01523 QLabel *explanationLabel;
01524 KComboBox *ownerPermCombo, *groupPermCombo, *othersPermCombo;
01525 QCheckBox *extraCheckbox;
01526 mode_t partialPermissions;
01527 KFilePermissionsPropsPlugin::PermissionsMode pmode;
01528 bool canChangePermissions;
01529 bool isIrregular;
01530 bool hasExtendedACL;
01531 KACL extendedACL;
01532 KACL defaultACL;
01533 bool fileSystemSupportsACLs;
01534
01535 KComboBox *grpCombo;
01536
01537 KLineEdit *usrEdit;
01538 KLineEdit *grpEdit;
01539
01540
01541 mode_t permissions;
01542
01543 QString strGroup;
01544
01545 QString strOwner;
01546 };
01547
01548 #define UniOwner (S_IRUSR|S_IWUSR|S_IXUSR)
01549 #define UniGroup (S_IRGRP|S_IWGRP|S_IXGRP)
01550 #define UniOthers (S_IROTH|S_IWOTH|S_IXOTH)
01551 #define UniRead (S_IRUSR|S_IRGRP|S_IROTH)
01552 #define UniWrite (S_IWUSR|S_IWGRP|S_IWOTH)
01553 #define UniExec (S_IXUSR|S_IXGRP|S_IXOTH)
01554 #define UniSpecial (S_ISUID|S_ISGID|S_ISVTX)
01555
01556
01557 const mode_t KFilePermissionsPropsPlugin::permissionsMasks[3] = {UniOwner, UniGroup, UniOthers};
01558 const mode_t KFilePermissionsPropsPlugin::standardPermissions[4] = { 0, UniRead, UniRead|UniWrite, (mode_t)-1 };
01559
01560
01561 const char *KFilePermissionsPropsPlugin::permissionsTexts[4][4] = {
01562 { I18N_NOOP("Forbidden"),
01563 I18N_NOOP("Can Read"),
01564 I18N_NOOP("Can Read & Write"),
01565 0 },
01566 { I18N_NOOP("Forbidden"),
01567 I18N_NOOP("Can View Content"),
01568 I18N_NOOP("Can View & Modify Content"),
01569 0 },
01570 { 0, 0, 0, 0},
01571 { I18N_NOOP("Forbidden"),
01572 I18N_NOOP("Can View Content & Read"),
01573 I18N_NOOP("Can View/Read & Modify/Write"),
01574 0 }
01575 };
01576
01577
01578 KFilePermissionsPropsPlugin::KFilePermissionsPropsPlugin( KPropertiesDialog *_props )
01579 : KPropertiesDialogPlugin( _props ),d(new KFilePermissionsPropsPluginPrivate)
01580 {
01581 d->cbRecursive = 0L;
01582 d->grpCombo = 0L; d->grpEdit = 0;
01583 d->usrEdit = 0L;
01584 QString path = properties->kurl().path(KUrl::RemoveTrailingSlash);
01585 QString fname = properties->kurl().fileName();
01586 bool isLocal = properties->kurl().isLocalFile();
01587 bool isTrash = ( properties->kurl().protocol().toLower() == "trash" );
01588 bool IamRoot = (geteuid() == 0);
01589
01590 const KFileItem item = properties->item();
01591 bool isLink = item.isLink();
01592 bool isDir = item.isDir();
01593 bool hasDir = item.isDir();
01594 d->permissions = item.permissions();
01595 d->partialPermissions = d->permissions;
01596 d->isIrregular = isIrregular(d->permissions, isDir, isLink);
01597 d->strOwner = item.user();
01598 d->strGroup = item.group();
01599 d->hasExtendedACL = item.ACL().isExtended() || item.defaultACL().isValid();
01600 d->extendedACL = item.ACL();
01601 d->defaultACL = item.defaultACL();
01602 d->fileSystemSupportsACLs = false;
01603
01604 if ( properties->items().count() > 1 )
01605 {
01606
01607 const KFileItemList items = properties->items();
01608 KFileItemList::const_iterator it = items.begin();
01609 const KFileItemList::const_iterator kend = items.end();
01610 for ( ++it ; it != kend; ++it )
01611 {
01612 const KUrl url = (*it).url();
01613 if (!d->isIrregular)
01614 d->isIrregular |= isIrregular((*it).permissions(),
01615 (*it).isDir() == isDir,
01616 (*it).isLink() == isLink);
01617 d->hasExtendedACL = d->hasExtendedACL || (*it).hasExtendedACL();
01618 if ( (*it).isLink() != isLink )
01619 isLink = false;
01620 if ( (*it).isDir() != isDir )
01621 isDir = false;
01622 hasDir |= (*it).isDir();
01623 if ( (*it).permissions() != d->permissions )
01624 {
01625 d->permissions &= (*it).permissions();
01626 d->partialPermissions |= (*it).permissions();
01627 }
01628 if ( (*it).user() != d->strOwner )
01629 d->strOwner.clear();
01630 if ( (*it).group() != d->strGroup )
01631 d->strGroup.clear();
01632 }
01633 }
01634
01635 if (isLink)
01636 d->pmode = PermissionsOnlyLinks;
01637 else if (isDir)
01638 d->pmode = PermissionsOnlyDirs;
01639 else if (hasDir)
01640 d->pmode = PermissionsMixed;
01641 else
01642 d->pmode = PermissionsOnlyFiles;
01643
01644
01645 d->partialPermissions = d->partialPermissions & ~d->permissions;
01646
01647 bool isMyFile = false;
01648
01649 if (isLocal && !d->strOwner.isEmpty()) {
01650 struct passwd *myself = getpwuid( geteuid() );
01651 if ( myself != 0L )
01652 {
01653 isMyFile = (d->strOwner == QString::fromLocal8Bit(myself->pw_name));
01654 } else
01655 kWarning() << "I don't exist ?! geteuid=" << geteuid();
01656 } else {
01657
01658
01659
01660 isMyFile = true;
01661 }
01662
01663 d->canChangePermissions = (isMyFile || IamRoot) && (!isLink);
01664
01665
01666
01667
01668 d->m_frame = new QFrame();
01669 properties->addPage( d->m_frame, i18n("&Permissions") );
01670
01671 QBoxLayout *box = new QVBoxLayout( d->m_frame );
01672 box->setMargin( 0 );
01673
01674 QWidget *l;
01675 QLabel *lbl;
01676 QGroupBox *gb;
01677 QGridLayout *gl;
01678 QPushButton* pbAdvancedPerm = 0;
01679
01680
01681 gb = new QGroupBox ( i18n("Access Permissions"), d->m_frame );
01682 box->addWidget (gb);
01683
01684 gl = new QGridLayout (gb);
01685 gl->setColumnStretch(1, 1);
01686
01687 l = d->explanationLabel = new QLabel( "", gb );
01688 if (isLink)
01689 d->explanationLabel->setText(i18np("This file is a link and does not have permissions.",
01690 "All files are links and do not have permissions.",
01691 properties->items().count()));
01692 else if (!d->canChangePermissions)
01693 d->explanationLabel->setText(i18n("Only the owner can change permissions."));
01694 gl->addWidget(l, 0, 0, 1, 2);
01695
01696 lbl = new QLabel( i18n("O&wner:"), gb);
01697 gl->addWidget(lbl, 1, 0, Qt::AlignRight);
01698 l = d->ownerPermCombo = new KComboBox(gb);
01699 lbl->setBuddy(l);
01700 gl->addWidget(l, 1, 1);
01701 connect(l, SIGNAL( activated(int) ), this, SIGNAL( changed() ));
01702 l->setWhatsThis(i18n("Specifies the actions that the owner is allowed to do."));
01703
01704 lbl = new QLabel( i18n("Gro&up:"), gb);
01705 gl->addWidget(lbl, 2, 0, Qt::AlignRight);
01706 l = d->groupPermCombo = new KComboBox(gb);
01707 lbl->setBuddy(l);
01708 gl->addWidget(l, 2, 1);
01709 connect(l, SIGNAL( activated(int) ), this, SIGNAL( changed() ));
01710 l->setWhatsThis(i18n("Specifies the actions that the members of the group are allowed to do."));
01711
01712 lbl = new QLabel( i18n("O&thers:"), gb);
01713 gl->addWidget(lbl, 3, 0, Qt::AlignRight);
01714 l = d->othersPermCombo = new KComboBox(gb);
01715 lbl->setBuddy(l);
01716 gl->addWidget(l, 3, 1);
01717 connect(l, SIGNAL( activated(int) ), this, SIGNAL( changed() ));
01718 l->setWhatsThis(i18n("Specifies the actions that all users, who are neither "
01719 "owner nor in the group, are allowed to do."));
01720
01721 if (!isLink) {
01722 l = d->extraCheckbox = new QCheckBox(hasDir ?
01723 i18n("Only own&er can rename and delete folder content") :
01724 i18n("Is &executable"),
01725 gb );
01726 connect( d->extraCheckbox, SIGNAL( clicked() ), this, SIGNAL( changed() ) );
01727 gl->addWidget(l, 4, 1);
01728 l->setWhatsThis(hasDir ? i18n("Enable this option to allow only the folder's owner to "
01729 "delete or rename the contained files and folders. Other "
01730 "users can only add new files, which requires the 'Modify "
01731 "Content' permission.")
01732 : i18n("Enable this option to mark the file as executable. This only makes "
01733 "sense for programs and scripts. It is required when you want to "
01734 "execute them."));
01735
01736 QLayoutItem *spacer = new QSpacerItem(0, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
01737 gl->addItem(spacer, 5, 0, 1, 3);
01738
01739 pbAdvancedPerm = new QPushButton(i18n("A&dvanced Permissions"), gb);
01740 gl->addWidget(pbAdvancedPerm, 6, 0, 1, 2, Qt::AlignRight);
01741 connect(pbAdvancedPerm, SIGNAL( clicked() ), this, SLOT( slotShowAdvancedPermissions() ));
01742 }
01743 else
01744 d->extraCheckbox = 0;
01745
01746
01747
01748 gb = new QGroupBox ( i18n("Ownership"), d->m_frame );
01749 box->addWidget (gb);
01750
01751 gl = new QGridLayout (gb);
01752 gl->addItem(new QSpacerItem(0, 10), 0, 0);
01753
01754
01755 l = new QLabel( i18n("User:"), gb );
01756 gl->addWidget (l, 1, 0, Qt::AlignRight);
01757
01758
01759
01760
01761
01762
01763 int i, maxEntries = 1000;
01764 struct passwd *user;
01765
01766
01767
01768
01769 if (IamRoot && isLocal)
01770 {
01771 d->usrEdit = new KLineEdit( gb );
01772 KCompletion *kcom = d->usrEdit->completionObject();
01773 kcom->setOrder(KCompletion::Sorted);
01774 setpwent();
01775 for (i=0; ((user = getpwent()) != 0L) && (i < maxEntries); ++i)
01776 kcom->addItem(QString::fromLatin1(user->pw_name));
01777 endpwent();
01778 d->usrEdit->setCompletionMode((i < maxEntries) ? KGlobalSettings::CompletionAuto :
01779 KGlobalSettings::CompletionNone);
01780 d->usrEdit->setText(d->strOwner);
01781 gl->addWidget(d->usrEdit, 1, 1);
01782 connect( d->usrEdit, SIGNAL( textChanged( const QString & ) ),
01783 this, SIGNAL( changed() ) );
01784 }
01785 else
01786 {
01787 l = new QLabel(d->strOwner, gb);
01788 gl->addWidget(l, 1, 1);
01789 }
01790
01791
01792
01793 QStringList groupList;
01794 QByteArray strUser;
01795 user = getpwuid(geteuid());
01796 if (user != 0L)
01797 strUser = user->pw_name;
01798
01799 #ifdef HAVE_GETGROUPLIST
01800
01801 int groupCount = 0;
01802 #ifdef Q_OS_MAC
01803 QVarLengthArray<int> groups;
01804 #else
01805 QVarLengthArray<gid_t> groups;
01806 #endif
01807 if (getgrouplist(strUser, user->pw_gid, NULL, &groupCount) < 0) {
01808 groups.resize(groupCount);
01809 if (groups.data())
01810 getgrouplist(strUser, user->pw_gid, groups.data(), &groupCount);
01811 else
01812 groupCount = 0;
01813 }
01814
01815 for (i = 0; i < groupCount; i++) {
01816 struct group *mygroup = getgrgid(groups[i]);
01817 if (mygroup)
01818 groupList += QString::fromLocal8Bit(mygroup->gr_name);
01819 }
01820 #endif // HAVE_GETGROUPLIST
01821
01822 bool isMyGroup = groupList.contains(d->strGroup);
01823
01824
01825
01826
01827 if (!isMyGroup)
01828 groupList += d->strGroup;
01829
01830 l = new QLabel( i18n("Group:"), gb );
01831 gl->addWidget (l, 2, 0, Qt::AlignRight);
01832
01833
01834
01835
01836
01837
01838
01839 if (IamRoot && isLocal)
01840 {
01841 d->grpEdit = new KLineEdit(gb);
01842 KCompletion *kcom = new KCompletion;
01843 kcom->setItems(groupList);
01844 d->grpEdit->setCompletionObject(kcom, true);
01845 d->grpEdit->setAutoDeleteCompletionObject( true );
01846 d->grpEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
01847 d->grpEdit->setText(d->strGroup);
01848 gl->addWidget(d->grpEdit, 2, 1);
01849 connect( d->grpEdit, SIGNAL( textChanged( const QString & ) ),
01850 this, SIGNAL( changed() ) );
01851 }
01852 else if ((groupList.count() > 1) && isMyFile && isLocal)
01853 {
01854 d->grpCombo = new KComboBox(gb);
01855 d->grpCombo->setObjectName(QLatin1String("combogrouplist"));
01856 d->grpCombo->addItems(groupList);
01857 d->grpCombo->setCurrentIndex(groupList.indexOf(d->strGroup));
01858 gl->addWidget(d->grpCombo, 2, 1);
01859 connect( d->grpCombo, SIGNAL( activated( int ) ),
01860 this, SIGNAL( changed() ) );
01861 }
01862 else
01863 {
01864 l = new QLabel(d->strGroup, gb);
01865 gl->addWidget(l, 2, 1);
01866 }
01867
01868 gl->setColumnStretch(2, 10);
01869
01870
01871 if ( hasDir && !isLink && !isTrash )
01872 {
01873 d->cbRecursive = new QCheckBox( i18n("Apply changes to all subfolders and their contents"), d->m_frame );
01874 connect( d->cbRecursive, SIGNAL( clicked() ), this, SIGNAL( changed() ) );
01875 box->addWidget( d->cbRecursive );
01876 }
01877
01878 updateAccessControls();
01879
01880
01881 if ( isTrash )
01882 {
01883
01884 enableAccessControls(false);
01885 if ( pbAdvancedPerm)
01886 pbAdvancedPerm->setEnabled(false);
01887 }
01888
01889 box->addStretch (10);
01890 }
01891
01892 #ifdef HAVE_POSIX_ACL
01893 static bool fileSystemSupportsACL( const QByteArray& path )
01894 {
01895 bool fileSystemSupportsACLs = false;
01896 #ifdef Q_OS_FREEBSD
01897 struct statfs buf;
01898 fileSystemSupportsACLs = ( statfs( path.data(), &buf ) == 0 ) && ( buf.f_flags & MNT_ACLS );
01899 #else
01900 fileSystemSupportsACLs =
01901 getxattr( path.data(), "system.posix_acl_access", NULL, 0 ) >= 0 || errno == ENODATA;
01902 #endif
01903 return fileSystemSupportsACLs;
01904 }
01905 #endif
01906
01907
01908 void KFilePermissionsPropsPlugin::slotShowAdvancedPermissions() {
01909
01910 bool isDir = (d->pmode == PermissionsOnlyDirs) || (d->pmode == PermissionsMixed);
01911 KDialog dlg( properties );
01912 dlg.setModal( true );
01913 dlg.setCaption( i18n("Advanced Permissions") );
01914 dlg.setButtons( KDialog::Ok | KDialog::Cancel );
01915
01916 QLabel *l, *cl[3];
01917 QGroupBox *gb;
01918 QGridLayout *gl;
01919
01920 QWidget *mainw = new QWidget( &dlg );
01921 QVBoxLayout *vbox = new QVBoxLayout(mainw);
01922
01923 gb = new QGroupBox ( i18n("Access Permissions"), mainw );
01924 vbox->addWidget(gb);
01925
01926 gl = new QGridLayout (gb);
01927 gl->addItem(new QSpacerItem(0, 10), 0, 0);
01928
01929 QVector<QWidget*> theNotSpecials;
01930
01931 l = new QLabel(i18n("Class"), gb );
01932 gl->addWidget(l, 1, 0);
01933 theNotSpecials.append( l );
01934
01935 if (isDir)
01936 l = new QLabel( i18n("Show\nEntries"), gb );
01937 else
01938 l = new QLabel( i18n("Read"), gb );
01939 gl->addWidget (l, 1, 1);
01940 theNotSpecials.append( l );
01941 QString readWhatsThis;
01942 if (isDir)
01943 readWhatsThis = i18n("This flag allows viewing the content of the folder.");
01944 else
01945 readWhatsThis = i18n("The Read flag allows viewing the content of the file.");
01946 l->setWhatsThis(readWhatsThis);
01947
01948 if (isDir)
01949 l = new QLabel( i18n("Write\nEntries"), gb );
01950 else
01951 l = new QLabel( i18n("Write"), gb );
01952 gl->addWidget (l, 1, 2);
01953 theNotSpecials.append( l );
01954 QString writeWhatsThis;
01955 if (isDir)
01956 writeWhatsThis = i18n("This flag allows adding, renaming and deleting of files. "
01957 "Note that deleting and renaming can be limited using the Sticky flag.");
01958 else
01959 writeWhatsThis = i18n("The Write flag allows modifying the content of the file.");
01960 l->setWhatsThis(writeWhatsThis);
01961
01962 QString execWhatsThis;
01963 if (isDir) {
01964 l = new QLabel( i18nc("Enter folder", "Enter"), gb );
01965 execWhatsThis = i18n("Enable this flag to allow entering the folder.");
01966 }
01967 else {
01968 l = new QLabel( i18n("Exec"), gb );
01969 execWhatsThis = i18n("Enable this flag to allow executing the file as a program.");
01970 }
01971 l->setWhatsThis(execWhatsThis);
01972 theNotSpecials.append( l );
01973
01974 QSize size = l->sizeHint();
01975 size.setWidth(size.width() + 15);
01976 l->setFixedSize(size);
01977 gl->addWidget (l, 1, 3);
01978
01979 l = new QLabel( i18n("Special"), gb );
01980 gl->addWidget(l, 1, 4, 1, 2);
01981 QString specialWhatsThis;
01982 if (isDir)
01983 specialWhatsThis = i18n("Special flag. Valid for the whole folder, the exact "
01984 "meaning of the flag can be seen in the right hand column.");
01985 else
01986 specialWhatsThis = i18n("Special flag. The exact meaning of the flag can be seen "
01987 "in the right hand column.");
01988 l->setWhatsThis(specialWhatsThis);
01989
01990 cl[0] = new QLabel( i18n("User"), gb );
01991 gl->addWidget (cl[0], 2, 0);
01992 theNotSpecials.append( cl[0] );
01993
01994 cl[1] = new QLabel( i18n("Group"), gb );
01995 gl->addWidget (cl[1], 3, 0);
01996 theNotSpecials.append( cl[1] );
01997
01998 cl[2] = new QLabel( i18n("Others"), gb );
01999 gl->addWidget (cl[2], 4, 0);
02000 theNotSpecials.append( cl[2] );
02001
02002 l = new QLabel(i18n("Set UID"), gb);
02003 gl->addWidget(l, 2, 5);
02004 QString setUidWhatsThis;
02005 if (isDir)
02006 setUidWhatsThis = i18n("If this flag is set, the owner of this folder will be "
02007 "the owner of all new files.");
02008 else
02009 setUidWhatsThis = i18n("If this file is an executable and the flag is set, it will "
02010 "be executed with the permissions of the owner.");
02011 l->setWhatsThis(setUidWhatsThis);
02012
02013 l = new QLabel(i18n("Set GID"), gb);
02014 gl->addWidget(l, 3, 5);
02015 QString setGidWhatsThis;
02016 if (isDir)
02017 setGidWhatsThis = i18n("If this flag is set, the group of this folder will be "
02018 "set for all new files.");
02019 else
02020 setGidWhatsThis = i18n("If this file is an executable and the flag is set, it will "
02021 "be executed with the permissions of the group.");
02022 l->setWhatsThis(setGidWhatsThis);
02023
02024 l = new QLabel(i18nc("File permission", "Sticky"), gb);
02025 gl->addWidget(l, 4, 5);
02026 QString stickyWhatsThis;
02027 if (isDir)
02028 stickyWhatsThis = i18n("If the Sticky flag is set on a folder, only the owner "
02029 "and root can delete or rename files. Otherwise everybody "
02030 "with write permissions can do this.");
02031 else
02032 stickyWhatsThis = i18n("The Sticky flag on a file is ignored on Linux, but may "
02033 "be used on some systems");
02034 l->setWhatsThis(stickyWhatsThis);
02035
02036 mode_t aPermissions, aPartialPermissions;
02037 mode_t dummy1, dummy2;
02038
02039 if (!d->isIrregular) {
02040 switch (d->pmode) {
02041 case PermissionsOnlyFiles:
02042 getPermissionMasks(aPartialPermissions,
02043 dummy1,
02044 aPermissions,
02045 dummy2);
02046 break;
02047 case PermissionsOnlyDirs:
02048 case PermissionsMixed:
02049 getPermissionMasks(dummy1,
02050 aPartialPermissions,
02051 dummy2,
02052 aPermissions);
02053 break;
02054 case PermissionsOnlyLinks:
02055 aPermissions = UniRead | UniWrite | UniExec | UniSpecial;
02056 aPartialPermissions = 0;
02057 break;
02058 }
02059 }
02060 else {
02061 aPermissions = d->permissions;
02062 aPartialPermissions = d->partialPermissions;
02063 }
02064
02065
02066 QCheckBox *cba[3][4];
02067 for (int row = 0; row < 3 ; ++row) {
02068 for (int col = 0; col < 4; ++col) {
02069 QCheckBox *cb = new QCheckBox(gb);
02070 if ( col != 3 ) theNotSpecials.append( cb );
02071 cba[row][col] = cb;
02072 cb->setChecked(aPermissions & fperm[row][col]);
02073 if ( aPartialPermissions & fperm[row][col] )
02074 {
02075 cb->setTristate();
02076 cb->setCheckState(Qt::PartiallyChecked);
02077 }
02078 else if (d->cbRecursive && d->cbRecursive->isChecked())
02079 cb->setTristate();
02080
02081 cb->setEnabled( d->canChangePermissions );
02082 gl->addWidget (cb, row+2, col+1);
02083 switch(col) {
02084 case 0:
02085 cb->setWhatsThis(readWhatsThis);
02086 break;
02087 case 1:
02088 cb->setWhatsThis(writeWhatsThis);
02089 break;
02090 case 2:
02091 cb->setWhatsThis(execWhatsThis);
02092 break;
02093 case 3:
02094 switch(row) {
02095 case 0:
02096 cb->setWhatsThis(setUidWhatsThis);
02097 break;
02098 case 1:
02099 cb->setWhatsThis(setGidWhatsThis);
02100 break;
02101 case 2:
02102 cb->setWhatsThis(stickyWhatsThis);
02103 break;
02104 }
02105 break;
02106 }
02107 }
02108 }
02109 gl->setColumnStretch(6, 10);
02110
02111 #ifdef HAVE_POSIX_ACL
02112 KACLEditWidget *extendedACLs = 0;
02113
02114
02115 if ( properties->items().count() == 1 ) {
02116 QByteArray path = QFile::encodeName( properties->item().url().toLocalFile() );
02117 d->fileSystemSupportsACLs = fileSystemSupportsACL( path );
02118 }
02119 if ( d->fileSystemSupportsACLs ) {
02120 std::for_each( theNotSpecials.begin(), theNotSpecials.end(), std::mem_fun( &QWidget::hide ) );
02121 extendedACLs = new KACLEditWidget( mainw );
02122 vbox->addWidget(extendedACLs);
02123 if ( d->extendedACL.isValid() && d->extendedACL.isExtended() )
02124 extendedACLs->setACL( d->extendedACL );
02125 else
02126 extendedACLs->setACL( KACL( aPermissions ) );
02127
02128 if ( d->defaultACL.isValid() )
02129 extendedACLs->setDefaultACL( d->defaultACL );
02130
02131 if ( properties->items().first().isDir() )
02132 extendedACLs->setAllowDefaults( true );
02133 }
02134 #endif
02135 dlg.setMainWidget( mainw );
02136 if (dlg.exec() != KDialog::Accepted)
02137 return;
02138
02139 mode_t andPermissions = mode_t(~0);
02140 mode_t orPermissions = 0;
02141 for (int row = 0; row < 3; ++row)
02142 for (int col = 0; col < 4; ++col) {
02143 switch (cba[row][col]->checkState())
02144 {
02145 case Qt::Checked:
02146 orPermissions |= fperm[row][col];
02147
02148 case Qt::Unchecked:
02149 andPermissions &= ~fperm[row][col];
02150 break;
02151 default:
02152 break;
02153 }
02154 }
02155
02156 d->isIrregular = false;
02157 const KFileItemList items = properties->items();
02158 KFileItemList::const_iterator it = items.begin();
02159 const KFileItemList::const_iterator kend = items.end();
02160 for ( ; it != kend; ++it ) {
02161 if (isIrregular(((*it).permissions() & andPermissions) | orPermissions,
02162 (*it).isDir(), (*it).isLink())) {
02163 d->isIrregular = true;
02164 break;
02165 }
02166 }
02167
02168 d->permissions = orPermissions;
02169 d->partialPermissions = andPermissions;
02170
02171 #ifdef HAVE_POSIX_ACL
02172
02173 if ( extendedACLs ) {
02174 d->extendedACL = extendedACLs->getACL();
02175 d->defaultACL = extendedACLs->getDefaultACL();
02176 d->hasExtendedACL = d->extendedACL.isExtended() || d->defaultACL.isValid();
02177 d->permissions = d->extendedACL.basePermissions();
02178 d->permissions |= ( andPermissions | orPermissions ) & ( S_ISUID|S_ISGID|S_ISVTX );
02179 }
02180 #endif
02181
02182 updateAccessControls();
02183 emit changed();
02184 }
02185
02186
02187
02188
02189
02190
02191 KFilePermissionsPropsPlugin::~KFilePermissionsPropsPlugin()
02192 {
02193 delete d;
02194 }
02195
02196 bool KFilePermissionsPropsPlugin::supports( const KFileItemList& )
02197 {
02198 return true;
02199 }
02200
02201
02202 void KFilePermissionsPropsPlugin::setComboContent(QComboBox *combo, PermissionsTarget target,
02203 mode_t permissions, mode_t partial) {
02204 combo->clear();
02205 if (d->isIrregular)
02206 return;
02207
02208 if (d->pmode == PermissionsOnlyLinks) {
02209 combo->addItem(i18n("Link"));
02210 combo->setCurrentIndex(0);
02211 return;
02212 }
02213
02214 mode_t tMask = permissionsMasks[target];
02215 int textIndex;
02216 for (textIndex = 0; standardPermissions[textIndex] != (mode_t)-1; textIndex++) {
02217 if ((standardPermissions[textIndex]&tMask) == (permissions&tMask&(UniRead|UniWrite)))
02218 break;
02219 }
02220 Q_ASSERT(standardPermissions[textIndex] != (mode_t)-1);
02221
02222 for (int i = 0; permissionsTexts[(int)d->pmode][i]; i++)
02223 combo->addItem(i18n(permissionsTexts[(int)d->pmode][i]));
02224
02225 if (partial & tMask & ~UniExec) {
02226 combo->addItem(i18n("Varying (No Change)"));
02227 combo->setCurrentIndex(3);
02228 }
02229 else {
02230 combo->setCurrentIndex(textIndex);
02231 }
02232 }
02233
02234
02235 bool KFilePermissionsPropsPlugin::isIrregular(mode_t permissions, bool isDir, bool isLink) {
02236 if (isLink)
02237 return false;
02238
02239 mode_t p = permissions;
02240 if (p & (S_ISUID | S_ISGID))
02241 return true;
02242 if (isDir) {
02243 p &= ~S_ISVTX;
02244
02245
02246 mode_t p0 = p & UniOwner;
02247 if ((p0 != 0) && (p0 != (S_IRUSR | S_IXUSR)) && (p0 != UniOwner))
02248 return true;
02249 p0 = p & UniGroup;
02250 if ((p0 != 0) && (p0 != (S_IRGRP | S_IXGRP)) && (p0 != UniGroup))
02251 return true;
02252 p0 = p & UniOthers;
02253 if ((p0 != 0) && (p0 != (S_IROTH | S_IXOTH)) && (p0 != UniOthers))
02254 return true;
02255 return false;
02256 }
02257 if (p & S_ISVTX)
02258 return true;
02259
02260
02261 mode_t p0 = p & UniOwner;
02262 bool usrXPossible = !p0;
02263 if (p0 & S_IXUSR) {
02264 if ((p0 == S_IXUSR) || (p0 == (S_IWUSR | S_IXUSR)))
02265 return true;
02266 usrXPossible = true;
02267 }
02268 else if (p0 == S_IWUSR)
02269 return true;
02270
02271 p0 = p & UniGroup;
02272 bool grpXPossible = !p0;
02273 if (p0 & S_IXGRP) {
02274 if ((p0 == S_IXGRP) || (p0 == (S_IWGRP | S_IXGRP)))
02275 return true;
02276 grpXPossible = true;
02277 }
02278 else if (p0 == S_IWGRP)
02279 return true;
02280 if (p0 == 0)
02281 grpXPossible = true;
02282
02283 p0 = p & UniOthers;
02284 bool othXPossible = !p0;
02285 if (p0 & S_IXOTH) {
02286 if ((p0 == S_IXOTH) || (p0 == (S_IWOTH | S_IXOTH)))
02287 return true;
02288 othXPossible = true;
02289 }
02290 else if (p0 == S_IWOTH)
02291 return true;
02292
02293
02294 return (p & UniExec) && !(usrXPossible && grpXPossible && othXPossible);
02295 }
02296
02297
02298 void KFilePermissionsPropsPlugin::enableAccessControls(bool enable) {
02299 d->ownerPermCombo->setEnabled(enable);
02300 d->groupPermCombo->setEnabled(enable);
02301 d->othersPermCombo->setEnabled(enable);
02302 if (d->extraCheckbox)
02303 d->extraCheckbox->setEnabled(enable);
02304 if ( d->cbRecursive )
02305 d->cbRecursive->setEnabled(enable);
02306 }
02307
02308
02309 void KFilePermissionsPropsPlugin::updateAccessControls() {
02310 setComboContent(d->ownerPermCombo, PermissionsOwner,
02311 d->permissions, d->partialPermissions);
02312 setComboContent(d->groupPermCombo, PermissionsGroup,
02313 d->permissions, d->partialPermissions);
02314 setComboContent(d->othersPermCombo, PermissionsOthers,
02315 d->permissions, d->partialPermissions);
02316
02317 switch(d->pmode) {
02318 case PermissionsOnlyLinks:
02319 enableAccessControls(false);
02320 break;
02321 case PermissionsOnlyFiles:
02322 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
02323 if (d->canChangePermissions)
02324 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
02325 i18np("This file uses advanced permissions",
02326 "These files use advanced permissions.",
02327 properties->items().count()) : "");
02328 if (d->partialPermissions & UniExec) {
02329 d->extraCheckbox->setTristate();
02330 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
02331 }
02332 else {
02333 d->extraCheckbox->setTristate(false);
02334 d->extraCheckbox->setChecked(d->permissions & UniExec);
02335 }
02336 break;
02337 case PermissionsOnlyDirs:
02338 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
02339
02340
02341 if ( d->cbRecursive )
02342 d->cbRecursive->setEnabled( d->canChangePermissions && !d->isIrregular );
02343
02344 if (d->canChangePermissions)
02345 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
02346 i18np("This folder uses advanced permissions.",
02347 "These folders use advanced permissions.",
02348 properties->items().count()) : "");
02349 if (d->partialPermissions & S_ISVTX) {
02350 d->extraCheckbox->setTristate();
02351 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
02352 }
02353 else {
02354 d->extraCheckbox->setTristate(false);
02355 d->extraCheckbox->setChecked(d->permissions & S_ISVTX);
02356 }
02357 break;
02358 case PermissionsMixed:
02359 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
02360 if (d->canChangePermissions)
02361 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
02362 i18n("These files use advanced permissions.") : "");
02363 break;
02364 if (d->partialPermissions & S_ISVTX) {
02365 d->extraCheckbox->setTristate();
02366 d->extraCheckbox->setCheckState(Qt::PartiallyChecked);
02367 }
02368 else {
02369 d->extraCheckbox->setTristate(false);
02370 d->extraCheckbox->setChecked(d->permissions & S_ISVTX);
02371 }
02372 break;
02373 }
02374 }
02375
02376
02377 void KFilePermissionsPropsPlugin::getPermissionMasks(mode_t &andFilePermissions,
02378 mode_t &andDirPermissions,
02379 mode_t &orFilePermissions,
02380 mode_t &orDirPermissions) {
02381 andFilePermissions = mode_t(~UniSpecial);
02382 andDirPermissions = mode_t(~(S_ISUID|S_ISGID));
02383 orFilePermissions = 0;
02384 orDirPermissions = 0;
02385 if (d->isIrregular)
02386 return;
02387
02388 mode_t m = standardPermissions[d->ownerPermCombo->currentIndex()];
02389 if (m != (mode_t) -1) {
02390 orFilePermissions |= m & UniOwner;
02391 if ((m & UniOwner) &&
02392 ((d->pmode == PermissionsMixed) ||
02393 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
02394 andFilePermissions &= ~(S_IRUSR | S_IWUSR);
02395 else {
02396 andFilePermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
02397 if ((m & S_IRUSR) && (d->extraCheckbox->checkState() == Qt::Checked))
02398 orFilePermissions |= S_IXUSR;
02399 }
02400
02401 orDirPermissions |= m & UniOwner;
02402 if (m & S_IRUSR)
02403 orDirPermissions |= S_IXUSR;
02404 andDirPermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
02405 }
02406
02407 m = standardPermissions[d->groupPermCombo->currentIndex()];
02408 if (m != (mode_t) -1) {
02409 orFilePermissions |= m & UniGroup;
02410 if ((m & UniGroup) &&
02411 ((d->pmode == PermissionsMixed) ||
02412 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
02413 andFilePermissions &= ~(S_IRGRP | S_IWGRP);
02414 else {
02415 andFilePermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
02416 if ((m & S_IRGRP) && (d->extraCheckbox->checkState() == Qt::Checked))
02417 orFilePermissions |= S_IXGRP;
02418 }
02419
02420 orDirPermissions |= m & UniGroup;
02421 if (m & S_IRGRP)
02422 orDirPermissions |= S_IXGRP;
02423 andDirPermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
02424 }
02425
02426 m = d->othersPermCombo->currentIndex() >= 0 ? standardPermissions[d->othersPermCombo->currentIndex()] : (mode_t)-1;
02427 if (m != (mode_t) -1) {
02428 orFilePermissions |= m & UniOthers;
02429 if ((m & UniOthers) &&
02430 ((d->pmode == PermissionsMixed) ||
02431 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->checkState() == Qt::PartiallyChecked))))
02432 andFilePermissions &= ~(S_IROTH | S_IWOTH);
02433 else {
02434 andFilePermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
02435 if ((m & S_IROTH) && (d->extraCheckbox->checkState() == Qt::Checked))
02436 orFilePermissions |= S_IXOTH;
02437 }
02438
02439 orDirPermissions |= m & UniOthers;
02440 if (m & S_IROTH)
02441 orDirPermissions |= S_IXOTH;
02442 andDirPermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
02443 }
02444
02445 if (((d->pmode == PermissionsMixed) || (d->pmode == PermissionsOnlyDirs)) &&
02446 (d->extraCheckbox->checkState() != Qt::PartiallyChecked)) {
02447 andDirPermissions &= ~S_ISVTX;
02448 if (d->extraCheckbox->checkState() == Qt::Checked)
02449 orDirPermissions |= S_ISVTX;
02450 }
02451 }
02452
02453 void KFilePermissionsPropsPlugin::applyChanges()
02454 {
02455 mode_t orFilePermissions;
02456 mode_t orDirPermissions;
02457 mode_t andFilePermissions;
02458 mode_t andDirPermissions;
02459
02460 if (!d->canChangePermissions)
02461 return;
02462
02463 if (!d->isIrregular)
02464 getPermissionMasks(andFilePermissions,
02465 andDirPermissions,
02466 orFilePermissions,
02467 orDirPermissions);
02468 else {
02469 orFilePermissions = d->permissions;
02470 andFilePermissions = d->partialPermissions;
02471 orDirPermissions = d->permissions;
02472 andDirPermissions = d->partialPermissions;
02473 }
02474
02475 QString owner, group;
02476 if (d->usrEdit)
02477 owner = d->usrEdit->text();
02478 if (d->grpEdit)
02479 group = d->grpEdit->text();
02480 else if (d->grpCombo)
02481 group = d->grpCombo->currentText();
02482
02483 if (owner == d->strOwner)
02484 owner.clear();
02485
02486 if (group == d->strGroup)
02487 group.clear();
02488
02489 bool recursive = d->cbRecursive && d->cbRecursive->isChecked();
02490 bool permissionChange = false;
02491
02492 KFileItemList files, dirs;
02493 const KFileItemList items = properties->items();
02494 KFileItemList::const_iterator it = items.begin();
02495 const KFileItemList::const_iterator kend = items.end();
02496 for ( ; it != kend; ++it ) {
02497 if ((*it).isDir()) {
02498 dirs.append(*it);
02499 if ((*it).permissions() != (((*it).permissions() & andDirPermissions) | orDirPermissions))
02500 permissionChange = true;
02501 }
02502 else if ((*it).isFile()) {
02503 files.append(*it);
02504 if ((*it).permissions() != (((*it).permissions() & andFilePermissions) | orFilePermissions))
02505 permissionChange = true;
02506 }
02507 }
02508
02509 const bool ACLChange = ( d->extendedACL != properties->item().ACL() );
02510 const bool defaultACLChange = ( d->defaultACL != properties->item().defaultACL() );
02511
02512 if (owner.isEmpty() && group.isEmpty() && !recursive
02513 && !permissionChange && !ACLChange && !defaultACLChange)
02514 return;
02515
02516 KIO::Job * job;
02517 if (files.count() > 0) {
02518 job = KIO::chmod( files, orFilePermissions, ~andFilePermissions,
02519 owner, group, false );
02520 if ( ACLChange && d->fileSystemSupportsACLs )
02521 job->addMetaData( "ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():"ACL_DELETE" );
02522 if ( defaultACLChange && d->fileSystemSupportsACLs )
02523 job->addMetaData( "DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():"ACL_DELETE" );
02524
02525 connect( job, SIGNAL( result( KJob * ) ),
02526 SLOT( slotChmodResult( KJob * ) ) );
02527 QEventLoop eventLoop;
02528 connect(this, SIGNAL(leaveModality()),
02529 &eventLoop, SLOT(quit()));
02530 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
02531 }
02532 if (dirs.count() > 0) {
02533 job = KIO::chmod( dirs, orDirPermissions, ~andDirPermissions,
02534 owner, group, recursive );
02535 if ( ACLChange && d->fileSystemSupportsACLs )
02536 job->addMetaData( "ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():"ACL_DELETE" );
02537 if ( defaultACLChange && d->fileSystemSupportsACLs )
02538 job->addMetaData( "DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():"ACL_DELETE" );
02539
02540 connect( job, SIGNAL( result( KJob * ) ),
02541 SLOT( slotChmodResult( KJob * ) ) );
02542 QEventLoop eventLoop;
02543 connect(this, SIGNAL(leaveModality()),
02544 &eventLoop, SLOT(quit()));
02545 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
02546 }
02547 }
02548
02549 void KFilePermissionsPropsPlugin::slotChmodResult( KJob * job )
02550 {
02551 kDebug(250) << "KFilePermissionsPropsPlugin::slotChmodResult";
02552 if (job->error())
02553 job->uiDelegate()->showErrorMessage();
02554
02555 emit leaveModality();
02556 }
02557
02558
02559
02560
02561 class KUrlPropsPlugin::KUrlPropsPluginPrivate
02562 {
02563 public:
02564 KUrlPropsPluginPrivate()
02565 {
02566 }
02567 ~KUrlPropsPluginPrivate()
02568 {
02569 }
02570
02571 QFrame *m_frame;
02572 KUrlRequester *URLEdit;
02573 QString URLStr;
02574 };
02575
02576 KUrlPropsPlugin::KUrlPropsPlugin( KPropertiesDialog *_props )
02577 : KPropertiesDialogPlugin( _props ),d(new KUrlPropsPluginPrivate)
02578 {
02579 d->m_frame = new QFrame();
02580 properties->addPage(d->m_frame, i18n("U&RL"));
02581 QVBoxLayout *layout = new QVBoxLayout(d->m_frame);
02582 layout->setMargin(0);
02583
02584 QLabel *l;
02585 l = new QLabel( d->m_frame );
02586 l->setObjectName( QLatin1String( "Label_1" ) );
02587 l->setText( i18n("URL:") );
02588 layout->addWidget(l, Qt::AlignRight);
02589
02590 d->URLEdit = new KUrlRequester( d->m_frame );
02591 layout->addWidget(d->URLEdit);
02592
02593 KUrl url = KIO::NetAccess::mostLocalUrl( properties->kurl(), properties );
02594 if (url.isLocalFile()) {
02595 QString path = url.toLocalFile();
02596
02597 QFile f( path );
02598 if ( !f.open( QIODevice::ReadOnly ) ) {
02599 return;
02600 }
02601 f.close();
02602
02603 KDesktopFile config( path );
02604 const KConfigGroup dg = config.desktopGroup();
02605 d->URLStr = dg.readPathEntry( "URL", QString() );
02606
02607 if (!d->URLStr.isEmpty()) {
02608 d->URLEdit->setUrl( KUrl(d->URLStr) );
02609 }
02610 }
02611
02612 connect( d->URLEdit, SIGNAL( textChanged( const QString & ) ),
02613 this, SIGNAL( changed() ) );
02614
02615 layout->addStretch (1);
02616 }
02617
02618 KUrlPropsPlugin::~KUrlPropsPlugin()
02619 {
02620 delete d;
02621 }
02622
02623
02624
02625
02626
02627
02628 bool KUrlPropsPlugin::supports( const KFileItemList& _items )
02629 {
02630 if ( _items.count() != 1 )
02631 return false;
02632 const KFileItem item = _items.first();
02633
02634 if (!item.isDesktopFile())
02635 return false;
02636
02637
02638 bool isLocal;
02639 KUrl url = item.mostLocalUrl(isLocal);
02640 if (!isLocal) {
02641 return false;
02642 }
02643
02644 KDesktopFile config( url.path() );
02645 return config.hasLinkType();
02646 }
02647
02648 void KUrlPropsPlugin::applyChanges()
02649 {
02650 KUrl url = KIO::NetAccess::mostLocalUrl( properties->kurl(), properties );
02651 if (!url.isLocalFile()) {
02652
02653 return;
02654 }
02655
02656 QString path = url.path();
02657
02658 QFile f( path );
02659 if ( !f.open( QIODevice::ReadWrite ) ) {
02660 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
02661 "sufficient access to write to <b>%1</b>.</qt>", path));
02662 return;
02663 }
02664 f.close();
02665
02666 KDesktopFile config( path );
02667 KConfigGroup dg = config.desktopGroup();
02668 dg.writeEntry( "Type", QString::fromLatin1("Link"));
02669 dg.writePathEntry( "URL", d->URLEdit->url().url() );
02670
02671
02672 if ( dg.hasKey("Name") )
02673 {
02674 QString nameStr = nameFromFileName(properties->kurl().fileName());
02675 dg.writeEntry( "Name", nameStr );
02676 dg.writeEntry( "Name", nameStr, KConfigBase::Persistent|KConfigBase::Localized );
02677
02678 }
02679 }
02680
02681
02682
02683
02684
02685
02686
02687
02688 class KDevicePropsPlugin::KDevicePropsPluginPrivate
02689 {
02690 public:
02691 KDevicePropsPluginPrivate()
02692 {
02693 }
02694 ~KDevicePropsPluginPrivate()
02695 {
02696 }
02697
02698 QFrame *m_frame;
02699 QStringList mountpointlist;
02700 QLabel *m_freeSpaceText;
02701 QLabel *m_freeSpaceLabel;
02702 QProgressBar *m_freeSpaceBar;
02703
02704 KComboBox* device;
02705 QLabel* mountpoint;
02706 QCheckBox* readonly;
02707 KIconButton* unmounted;
02708
02709 QStringList m_devicelist;
02710 };
02711
02712 KDevicePropsPlugin::KDevicePropsPlugin( KPropertiesDialog *_props ) : KPropertiesDialogPlugin( _props ),d(new KDevicePropsPluginPrivate)
02713 {
02714 d->m_frame = new QFrame();
02715 properties->addPage(d->m_frame, i18n("De&vice"));
02716
02717 QStringList devices;
02718 const KMountPoint::List mountPoints = KMountPoint::possibleMountPoints();
02719
02720 for(KMountPoint::List::ConstIterator it = mountPoints.begin();
02721 it != mountPoints.end(); ++it)
02722 {
02723 const KMountPoint::Ptr mp = (*it);
02724 QString mountPoint = mp->mountPoint();
02725 QString device = mp->mountedFrom();
02726 kDebug()<<"mountPoint :"<<mountPoint<<" device :"<<device<<" mp->mountType() :"<<mp->mountType();
02727
02728 if ((mountPoint != "-") && (mountPoint != "none") && !mountPoint.isEmpty()
02729 && device != "none")
02730 {
02731 devices.append( device + QString::fromLatin1(" (")
02732 + mountPoint + QString::fromLatin1(")") );
02733 d->m_devicelist.append(device);
02734 d->mountpointlist.append(mountPoint);
02735 }
02736 }
02737
02738 QGridLayout *layout = new QGridLayout( d->m_frame );
02739
02740 layout->setMargin(0);
02741 layout->setColumnStretch(1, 1);
02742
02743 QLabel* label;
02744 label = new QLabel( d->m_frame );
02745 label->setText( devices.count() == 0 ?
02746 i18n("Device (/dev/fd0):") :
02747 i18n("Device:") );
02748 layout->addWidget(label, 0, 0, Qt::AlignRight);
02749
02750 d->device = new KComboBox( d->m_frame );
02751 d->device->setObjectName( QLatin1String( "ComboBox_device" ) );
02752 d->device->setEditable( true );
02753 d->device->addItems( devices );
02754 layout->addWidget(d->device, 0, 1);
02755 connect( d->device, SIGNAL( activated( int ) ),
02756 this, SLOT( slotActivated( int ) ) );
02757
02758 d->readonly = new QCheckBox( d->m_frame );
02759 d->readonly->setObjectName( QLatin1String( "CheckBox_readonly" ) );
02760 d->readonly->setText( i18n("Read only") );
02761 layout->addWidget(d->readonly, 1, 1);
02762
02763 label = new QLabel( d->m_frame );
02764 label->setText( i18n("File system:") );
02765 layout->addWidget(label, 2, 0, Qt::AlignRight);
02766
02767 QLabel *fileSystem = new QLabel( d->m_frame );
02768 layout->addWidget(fileSystem, 2, 1);
02769
02770 label = new QLabel( d->m_frame );
02771 label->setText( devices.count()==0 ?
02772 i18n("Mount point (/mnt/floppy):") :
02773 i18n("Mount point:"));
02774 layout->addWidget(label, 3, 0, Qt::AlignRight);
02775
02776 d->mountpoint = new QLabel( d->m_frame );
02777 d->mountpoint->setObjectName( QLatin1String( "LineEdit_mountpoint" ) );
02778
02779 layout->addWidget(d->mountpoint, 3, 1);
02780
02781
02782 d->m_freeSpaceText = new QLabel(i18n("Device usage:"), d->m_frame );
02783 layout->addWidget(d->m_freeSpaceText, 4, 0, Qt::AlignRight);
02784
02785 d->m_freeSpaceLabel = new QLabel( d->m_frame );
02786 layout->addWidget( d->m_freeSpaceLabel, 4, 1 );
02787
02788 d->m_freeSpaceBar = new QProgressBar( d->m_frame );
02789 d->m_freeSpaceBar->setObjectName( "freeSpaceBar" );
02790 layout->addWidget(d->m_freeSpaceBar, 5, 0, 1, 2);
02791
02792
02793 d->m_freeSpaceText->hide();
02794 d->m_freeSpaceLabel->hide();
02795 d->m_freeSpaceBar->hide();
02796
02797 KSeparator* sep = new KSeparator( Qt::Horizontal, d->m_frame);
02798 layout->addWidget(sep, 6, 0, 1, 2);
02799
02800 d->unmounted = new KIconButton( d->m_frame );
02801 int bsize = 66 + 2 * d->unmounted->style()->pixelMetric(QStyle::PM_ButtonMargin);
02802 d->unmounted->setFixedSize(bsize, bsize);
02803 d->unmounted->setIconType(KIconLoader::Desktop, KIconLoader::Device);
02804 layout->addWidget(d->unmounted, 7, 0);
02805
02806 label = new QLabel( i18n("Unmounted Icon"), d->m_frame );
02807 layout->addWidget(label, 7, 1);
02808
02809 layout->setRowStretch(8, 1);
02810
02811 KUrl url = KIO::NetAccess::mostLocalUrl( _props->kurl(), _props );
02812 if (!url.isLocalFile()) {
02813 return;
02814 }
02815 QString path = url.toLocalFile();
02816
02817 QFile f( path );
02818 if ( !f.open( QIODevice::ReadOnly ) )
02819 return;
02820 f.close();
02821
02822 const KDesktopFile _config( path );
02823 const KConfigGroup config = _config.desktopGroup();
02824 QString deviceStr = config.readEntry( "Dev" );
02825 QString mountPointStr = config.readEntry( "MountPoint" );
02826 bool ro = config.readEntry( "ReadOnly", false );
02827 QString unmountedStr = config.readEntry( "UnmountIcon" );
02828
02829 fileSystem->setText(config.readEntry("FSType"));
02830
02831 d->device->setEditText( deviceStr );
02832 if ( !deviceStr.isEmpty() ) {
02833
02834 int index = d->m_devicelist.indexOf(deviceStr);
02835 if (index != -1)
02836 {
02837
02838 slotActivated( index );
02839 }
02840 }
02841
02842 if ( !mountPointStr.isEmpty() )
02843 {
02844 d->mountpoint->setText( mountPointStr );
02845 updateInfo();
02846 }
02847
02848 d->readonly->setChecked( ro );
02849
02850 if ( unmountedStr.isEmpty() )
02851 unmountedStr = KMimeType::defaultMimeTypePtr()->iconName();
02852
02853 d->unmounted->setIcon( unmountedStr );
02854
02855 connect( d->device, SIGNAL( activated( int ) ),
02856 this, SIGNAL( changed() ) );
02857 connect( d->device, SIGNAL( textChanged( const QString & ) ),
02858 this, SIGNAL( changed() ) );
02859 connect( d->readonly, SIGNAL( toggled( bool ) ),
02860 this, SIGNAL( changed() ) );
02861 connect( d->unmounted, SIGNAL( iconChanged( const QString& ) ),
02862 this, SIGNAL( changed() ) );
02863
02864 connect( d->device, SIGNAL( textChanged( const QString & ) ),
02865 this, SLOT( slotDeviceChanged() ) );
02866 }
02867
02868 KDevicePropsPlugin::~KDevicePropsPlugin()
02869 {
02870 delete d;
02871 }
02872
02873
02874
02875
02876
02877
02878 void KDevicePropsPlugin::updateInfo()
02879 {
02880
02881 d->m_freeSpaceText->hide();
02882 d->m_freeSpaceLabel->hide();
02883 d->m_freeSpaceBar->hide();
02884
02885 if ( !d->mountpoint->text().isEmpty() )
02886 {
02887 KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( d->mountpoint->text() );
02888 slotFoundMountPoint( info.mountPoint(), info.size()/1024, info.used()/1024, info.available()/1024);
02889 }
02890 }
02891
02892 void KDevicePropsPlugin::slotActivated( int index )
02893 {
02894
02895
02896 if (index < d->m_devicelist.count()) {
02897
02898 d->device->setEditText(d->m_devicelist[index]);
02899 d->mountpoint->setText(d->mountpointlist[index]);
02900 }
02901
02902 updateInfo();
02903 }
02904
02905 void KDevicePropsPlugin::slotDeviceChanged()
02906 {
02907
02908 int index = d->m_devicelist.indexOf( d->device->currentText() );
02909 if ( index != -1 )
02910 d->mountpoint->setText( d->mountpointlist[index] );
02911 else
02912 d->mountpoint->setText( QString() );
02913
02914 updateInfo();
02915 }
02916
02917 void KDevicePropsPlugin::slotFoundMountPoint( const QString&,
02918 quint64 kibSize,
02919 quint64 ,
02920 quint64 kibAvail )
02921 {
02922 d->m_freeSpaceText->show();
02923 d->m_freeSpaceLabel->show();
02924
02925 int percUsed = 100 - (int)(100.0 * kibAvail / kibSize);
02926
02927 d->m_freeSpaceLabel->setText(
02928 i18nc("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)",
02929 KIO::convertSizeFromKiB(kibAvail),
02930 KIO::convertSizeFromKiB(kibSize),
02931 100 - (int)(100.0 * kibAvail / kibSize) ));
02932
02933 d->m_freeSpaceBar->setRange(0, 100);
02934 d->m_freeSpaceBar->setValue(percUsed);
02935 d->m_freeSpaceBar->show();
02936 }
02937
02938 bool KDevicePropsPlugin::supports( const KFileItemList& _items )
02939 {
02940 if ( _items.count() != 1 )
02941 return false;
02942 const KFileItem item = _items.first();
02943
02944 if (!item.isDesktopFile())
02945 return false;
02946
02947
02948 bool isLocal;
02949 KUrl url = item.mostLocalUrl(isLocal);
02950 if (!isLocal) {
02951 return false;
02952 }
02953
02954 KDesktopFile config( url.path() );
02955 return config.hasDeviceType();
02956 }
02957
02958 void KDevicePropsPlugin::applyChanges()
02959 {
02960 KUrl url = KIO::NetAccess::mostLocalUrl( properties->kurl(), properties );
02961 if ( !url.isLocalFile() )
02962 return;
02963 QString path = url.toLocalFile();
02964
02965 QFile f( path );
02966 if ( !f.open( QIODevice::ReadWrite ) )
02967 {
02968 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have sufficient "
02969 "access to write to <b>%1</b>.</qt>", path));
02970 return;
02971 }
02972 f.close();
02973
02974 KDesktopFile _config( path );
02975 KConfigGroup config = _config.desktopGroup();
02976 config.writeEntry( "Type", QString::fromLatin1("FSDevice") );
02977
02978 config.writeEntry( "Dev", d->device->currentText() );
02979 config.writeEntry( "MountPoint", d->mountpoint->text() );
02980
02981 config.writeEntry( "UnmountIcon", d->unmounted->icon() );
02982 kDebug(250) << "d->unmounted->icon() = " << d->unmounted->icon();
02983
02984 config.writeEntry( "ReadOnly", d->readonly->isChecked() );
02985
02986 config.sync();
02987 }
02988
02989
02990
02991
02992
02993
02994
02995
02996 class KDesktopPropsPlugin::KDesktopPropsPluginPrivate
02997 {
02998 public:
02999 KDesktopPropsPluginPrivate()
03000 : w( new Ui_KPropertiesDesktopBase )
03001 , m_frame( new QFrame() )
03002 {
03003 }
03004 ~KDesktopPropsPluginPrivate()
03005 {
03006 delete w;
03007 }
03008 Ui_KPropertiesDesktopBase* w;
03009 QWidget *m_frame;
03010
03011 QString m_origCommandStr;
03012 QString m_terminalOptionStr;
03013 QString m_suidUserStr;
03014 QString m_dbusStartupType;
03015 QString m_dbusServiceName;
03016 bool m_terminalBool;
03017 bool m_suidBool;
03018 bool m_startupBool;
03019 bool m_systrayBool;
03020 };
03021
03022 KDesktopPropsPlugin::KDesktopPropsPlugin( KPropertiesDialog *_props )
03023 : KPropertiesDialogPlugin( _props ), d( new KDesktopPropsPluginPrivate )
03024 {
03025 d->w->setupUi(d->m_frame);
03026
03027 properties->addPage(d->m_frame, i18n("&Application"));
03028
03029 bool bKDesktopMode = (qApp->objectName() == "kdesktop");
03030
03031 if (bKDesktopMode)
03032 {
03033
03034 d->w->nameEdit->hide();
03035 d->w->nameLabel->hide();
03036 }
03037
03038 d->w->pathEdit->setMode(KFile::Directory | KFile::LocalOnly);
03039 d->w->pathEdit->lineEdit()->setAcceptDrops(false);
03040
03041 connect( d->w->nameEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03042 connect( d->w->genNameEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03043 connect( d->w->commentEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03044 connect( d->w->commandEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03045 connect( d->w->pathEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03046
03047 connect( d->w->browseButton, SIGNAL( clicked() ), this, SLOT( slotBrowseExec() ) );
03048 connect( d->w->addFiletypeButton, SIGNAL( clicked() ), this, SLOT( slotAddFiletype() ) );
03049 connect( d->w->delFiletypeButton, SIGNAL( clicked() ), this, SLOT( slotDelFiletype() ) );
03050 connect( d->w->advancedButton, SIGNAL( clicked() ), this, SLOT( slotAdvanced() ) );
03051
03052
03053
03054 KUrl url = KIO::NetAccess::mostLocalUrl( _props->kurl(), _props );
03055 if (!url.isLocalFile()) {
03056 return;
03057 }
03058 QString path = url.toLocalFile();
03059
03060 QFile f( path );
03061 if ( !f.open( QIODevice::ReadOnly ) )
03062 return;
03063 f.close();
03064
03065 KDesktopFile _config( path );
03066 KConfigGroup config = _config.desktopGroup();
03067 QString nameStr = _config.readName();
03068 QString genNameStr = _config.readGenericName();
03069 QString commentStr = _config.readComment();
03070 QString commandStr = config.readEntry( "Exec", QString() );
03071 if (commandStr.startsWith(QLatin1String("ksystraycmd ")))
03072 {
03073 commandStr.remove(0, 12);
03074 d->m_systrayBool = true;
03075 }
03076 else
03077 d->m_systrayBool = false;
03078
03079 d->m_origCommandStr = commandStr;
03080 QString pathStr = config.readEntry( "Path", QString() );
03081 d->m_terminalBool = config.readEntry( "Terminal", false );
03082 d->m_terminalOptionStr = config.readEntry( "TerminalOptions" );
03083 d->m_suidBool = config.readEntry( "X-KDE-SubstituteUID", false );
03084 d->m_suidUserStr = config.readEntry( "X-KDE-Username" );
03085 if( config.hasKey( "StartupNotify" ))
03086 d->m_startupBool = config.readEntry( "StartupNotify", true );
03087 else
03088 d->m_startupBool = config.readEntry( "X-KDE-StartupNotify", true );
03089 d->m_dbusStartupType = config.readEntry("X-DBUS-StartupType").toLower();
03090
03091
03092 d->m_dbusServiceName = config.readEntry("X-DBUS-ServiceName");
03093
03094 const QStringList mimeTypes = config.readXdgListEntry( "MimeType" );
03095
03096 if ( nameStr.isEmpty() || bKDesktopMode ) {
03097
03098
03099
03100 setDirty();
03101 }
03102 if ( !bKDesktopMode )
03103 d->w->nameEdit->setText(nameStr);
03104
03105 d->w->genNameEdit->setText( genNameStr );
03106 d->w->commentEdit->setText( commentStr );
03107 d->w->commandEdit->setText( commandStr );
03108 d->w->pathEdit->lineEdit()->setText( pathStr );
03109
03110
03111
03112
03113 KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
03114 for(QStringList::ConstIterator it = mimeTypes.begin();
03115 it != mimeTypes.end(); )
03116 {
03117 KMimeType::Ptr p = KMimeType::mimeType(*it, KMimeType::ResolveAliases);
03118 ++it;
03119 QString preference;
03120 if (it != mimeTypes.end())
03121 {
03122 bool numeric;
03123 (*it).toInt(&numeric);
03124 if (numeric)
03125 {
03126 preference = *it;
03127 ++it;
03128 }
03129 }
03130 if (p)
03131 {
03132 QTreeWidgetItem *item = new QTreeWidgetItem();
03133 item->setText(0, p->name());
03134 item->setText(1, p->comment());
03135 item->setText(2, preference);
03136 d->w->filetypeList->addTopLevelItem(item);
03137 }
03138 }
03139 d->w->filetypeList->resizeColumnToContents(0);
03140
03141 }
03142
03143 KDesktopPropsPlugin::~KDesktopPropsPlugin()
03144 {
03145 delete d;
03146 }
03147
03148 void KDesktopPropsPlugin::slotAddFiletype()
03149 {
03150 KMimeTypeChooserDialog dlg( i18n("Add File Type for %1", properties->kurl().fileName()),
03151 i18n("Select one or more file types to add:"),
03152 QStringList(),
03153 QString(),
03154 QStringList(),
03155 KMimeTypeChooser::Comments|KMimeTypeChooser::Patterns,
03156 d->m_frame );
03157
03158 if (dlg.exec() == KDialog::Accepted)
03159 {
03160 foreach(const QString &mimetype, dlg.chooser()->mimeTypes())
03161 {
03162 KMimeType::Ptr p = KMimeType::mimeType(mimetype);
03163 if (!p)
03164 continue;
03165
03166 bool found = false;
03167 int count = d->w->filetypeList->topLevelItemCount();
03168 for (int i = 0; !found && i < count; ++i) {
03169 if (d->w->filetypeList->topLevelItem(i)->text(0) == mimetype) {
03170 found = true;
03171 }
03172 }
03173 if (!found) {
03174 QTreeWidgetItem *item = new QTreeWidgetItem();
03175 item->setText(0, p->name());
03176 item->setText(1, p->comment());
03177 d->w->filetypeList->addTopLevelItem(item);
03178 }
03179 d->w->filetypeList->resizeColumnToContents(0);
03180 }
03181 }
03182 emit changed();
03183 }
03184
03185 void KDesktopPropsPlugin::slotDelFiletype()
03186 {
03187 QTreeWidgetItem *cur = d->w->filetypeList->currentItem();
03188 if (cur) {
03189 delete cur;
03190 emit changed();
03191 }
03192 }
03193
03194 void KDesktopPropsPlugin::checkCommandChanged()
03195 {
03196 if (KRun::binaryName(d->w->commandEdit->text(), true) !=
03197 KRun::binaryName(d->m_origCommandStr, true))
03198 {
03199 d->m_origCommandStr = d->w->commandEdit->text();
03200 d->m_dbusStartupType.clear();
03201 d->m_dbusServiceName.clear();
03202 }
03203 }
03204
03205 void KDesktopPropsPlugin::applyChanges()
03206 {
03207 kDebug(250) << "KDesktopPropsPlugin::applyChanges";
03208
03209 KUrl url = KIO::NetAccess::mostLocalUrl( properties->kurl(), properties );
03210 if (!url.isLocalFile()) {
03211
03212 return;
03213 }
03214 QString path = url.toLocalFile();
03215
03216 QFile f( path );
03217
03218 if ( !f.open( QIODevice::ReadWrite ) ) {
03219 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
03220 "sufficient access to write to <b>%1</b>.</qt>", path));
03221 return;
03222 }
03223 f.close();
03224
03225
03226
03227 checkCommandChanged();
03228
03229 KDesktopFile _config( path );
03230 KConfigGroup config = _config.desktopGroup();
03231 config.writeEntry( "Type", QString::fromLatin1("Application"));
03232 config.writeEntry( "Comment", d->w->commentEdit->text() );
03233 config.writeEntry( "Comment", d->w->commentEdit->text(), KConfigGroup::Persistent|KConfigGroup::Localized );
03234 config.writeEntry( "GenericName", d->w->genNameEdit->text() );
03235 config.writeEntry( "GenericName", d->w->genNameEdit->text(), KConfigGroup::Persistent|KConfigGroup::Localized );
03236
03237 if (d->m_systrayBool)
03238 config.writeEntry( "Exec", d->w->commandEdit->text().prepend("ksystraycmd ") );
03239 else
03240 config.writeEntry( "Exec", d->w->commandEdit->text() );
03241 config.writeEntry( "Path", d->w->pathEdit->lineEdit()->text() );
03242
03243
03244 QStringList mimeTypes;
03245 int count = d->w->filetypeList->topLevelItemCount();
03246 for (int i = 0; i < count; ++i) {
03247 QTreeWidgetItem *item = d->w->filetypeList->topLevelItem(i);
03248 QString preference = item->text(2);
03249 mimeTypes.append(item->text(0));
03250 if (!preference.isEmpty())
03251 mimeTypes.append(preference);
03252 }
03253
03254 kDebug() << mimeTypes;
03255 config.writeXdgListEntry( "MimeType", mimeTypes );
03256
03257 if ( !d->w->nameEdit->isHidden() ) {
03258 QString nameStr = d->w->nameEdit->text();
03259 config.writeEntry( "Name", nameStr );
03260 config.writeEntry( "Name", nameStr, KConfigGroup::Persistent|KConfigGroup::Localized );
03261 }
03262
03263 config.writeEntry("Terminal", d->m_terminalBool);
03264 config.writeEntry("TerminalOptions", d->m_terminalOptionStr);
03265 config.writeEntry("X-KDE-SubstituteUID", d->m_suidBool);
03266 config.writeEntry("X-KDE-Username", d->m_suidUserStr);
03267 config.writeEntry("StartupNotify", d->m_startupBool);
03268 config.writeEntry("X-DBUS-StartupType", d->m_dbusStartupType);
03269 config.writeEntry("X-DBUS-ServiceName", d->m_dbusServiceName);
03270 config.sync();
03271
03272
03273 QString sycocaPath = KGlobal::dirs()->relativeLocation("apps", path);
03274 bool updateNeeded = !sycocaPath.startsWith('/');
03275 if (!updateNeeded)
03276 {
03277 sycocaPath = KGlobal::dirs()->relativeLocation("xdgdata-apps", path);
03278 updateNeeded = !sycocaPath.startsWith('/');
03279 }
03280 if (updateNeeded)
03281 KBuildSycocaProgressDialog::rebuildKSycoca(d->m_frame);
03282 }
03283
03284
03285 void KDesktopPropsPlugin::slotBrowseExec()
03286 {
03287 KUrl f = KFileDialog::getOpenUrl( KUrl(),
03288 QString(), d->m_frame );
03289 if ( f.isEmpty() )
03290 return;
03291
03292 if ( !f.isLocalFile()) {
03293 KMessageBox::sorry(d->m_frame, i18n("Only executables on local file systems are supported."));
03294 return;
03295 }
03296
03297 QString path = f.toLocalFile();
03298 path = KShell::quoteArg( path );
03299 d->w->commandEdit->setText( path );
03300 }
03301
03302 void KDesktopPropsPlugin::slotAdvanced()
03303 {
03304 KDialog dlg( d->m_frame );
03305 dlg.setObjectName( "KPropertiesDesktopAdv" );
03306 dlg.setModal( true );
03307 dlg.setCaption( i18n("Advanced Options for %1", properties->kurl().fileName()) );
03308 dlg.setButtons( KDialog::Ok | KDialog::Cancel );
03309 dlg.setDefaultButton( KDialog::Ok );
03310 Ui_KPropertiesDesktopAdvBase w;
03311 w.setupUi(dlg.mainWidget());
03312
03313
03314
03315 checkCommandChanged();
03316
03317
03318
03319 KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
03320 QString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
03321 QString::fromLatin1("konsole"));
03322
03323 bool terminalCloseBool = false;
03324
03325 if (preferredTerminal == "konsole")
03326 {
03327 terminalCloseBool = (d->m_terminalOptionStr.contains( "--noclose" ) > 0);
03328 w.terminalCloseCheck->setChecked(terminalCloseBool);
03329 d->m_terminalOptionStr.remove( "--noclose");
03330 }
03331 else
03332 {
03333 w.terminalCloseCheck->hide();
03334 }
03335
03336 w.terminalCheck->setChecked(d->m_terminalBool);
03337 w.terminalEdit->setText(d->m_terminalOptionStr);
03338 w.terminalCloseCheck->setEnabled(d->m_terminalBool);
03339 w.terminalEdit->setEnabled(d->m_terminalBool);
03340 w.terminalEditLabel->setEnabled(d->m_terminalBool);
03341
03342 w.suidCheck->setChecked(d->m_suidBool);
03343 w.suidEdit->setText(d->m_suidUserStr);
03344 w.suidEdit->setEnabled(d->m_suidBool);
03345 w.suidEditLabel->setEnabled(d->m_suidBool);
03346
03347 w.startupInfoCheck->setChecked(d->m_startupBool);
03348 w.systrayCheck->setChecked(d->m_systrayBool);
03349
03350 if (d->m_dbusStartupType == "unique")
03351 w.dbusCombo->setCurrentIndex(2);
03352 else if (d->m_dbusStartupType == "multi")
03353 w.dbusCombo->setCurrentIndex(1);
03354 else if (d->m_dbusStartupType == "wait")
03355 w.dbusCombo->setCurrentIndex(3);
03356 else
03357 w.dbusCombo->setCurrentIndex(0);
03358
03359
03360 KCompletion *kcom = new KCompletion;
03361 kcom->setOrder(KCompletion::Sorted);
03362 struct passwd *pw;
03363 int i, maxEntries = 1000;
03364 setpwent();
03365 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
03366 kcom->addItem(QString::fromLatin1(pw->pw_name));
03367 endpwent();
03368 if (i < maxEntries)
03369 {
03370 w.suidEdit->setCompletionObject(kcom, true);
03371 w.suidEdit->setAutoDeleteCompletionObject( true );
03372 w.suidEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
03373 }
03374 else
03375 {
03376 delete kcom;
03377 }
03378
03379 connect( w.terminalEdit, SIGNAL( textChanged( const QString & ) ),
03380 this, SIGNAL( changed() ) );
03381 connect( w.terminalCloseCheck, SIGNAL( toggled( bool ) ),
03382 this, SIGNAL( changed() ) );
03383 connect( w.terminalCheck, SIGNAL( toggled( bool ) ),
03384 this, SIGNAL( changed() ) );
03385 connect( w.suidCheck, SIGNAL( toggled( bool ) ),
03386 this, SIGNAL( changed() ) );
03387 connect( w.suidEdit, SIGNAL( textChanged( const QString & ) ),
03388 this, SIGNAL( changed() ) );
03389 connect( w.startupInfoCheck, SIGNAL( toggled( bool ) ),
03390 this, SIGNAL( changed() ) );
03391 connect( w.systrayCheck, SIGNAL( toggled( bool ) ),
03392 this, SIGNAL( changed() ) );
03393 connect( w.dbusCombo, SIGNAL( activated( int ) ),
03394 this, SIGNAL( changed() ) );
03395
03396 if ( dlg.exec() == QDialog::Accepted )
03397 {
03398 d->m_terminalOptionStr = w.terminalEdit->text().trimmed();
03399 d->m_terminalBool = w.terminalCheck->isChecked();
03400 d->m_suidBool = w.suidCheck->isChecked();
03401 d->m_suidUserStr = w.suidEdit->text().trimmed();
03402 d->m_startupBool = w.startupInfoCheck->isChecked();
03403 d->m_systrayBool = w.systrayCheck->isChecked();
03404
03405 if (w.terminalCloseCheck->isChecked())
03406 {
03407 d->m_terminalOptionStr.append(" --noclose");
03408 }
03409
03410 switch(w.dbusCombo->currentIndex())
03411 {
03412 case 1: d->m_dbusStartupType = "multi"; break;
03413 case 2: d->m_dbusStartupType = "unique"; break;
03414 case 3: d->m_dbusStartupType = "wait"; break;
03415 default: d->m_dbusStartupType = "none"; break;
03416 }
03417 }
03418 }
03419
03420 bool KDesktopPropsPlugin::supports( const KFileItemList& _items )
03421 {
03422 if ( _items.count() != 1 ) {
03423 return false;
03424 }
03425
03426 const KFileItem item = _items.first();
03427
03428
03429 if (!item.isDesktopFile()) {
03430 return false;
03431 }
03432
03433
03434 bool isLocal;
03435 KUrl url = item.mostLocalUrl( isLocal );
03436 if (!isLocal) {
03437 return false;
03438 }
03439
03440 KDesktopFile config( url.path() );
03441 return config.hasApplicationType() &&
03442 KAuthorized::authorize("run_desktop_files") &&
03443 KAuthorized::authorize("shell_access");
03444 }
03445
03446 #include "kpropertiesdialog.moc"
03447 #include "kpropertiesdialog_p.moc"
03448