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