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