summaryrefslogtreecommitdiffstats
path: root/tdeio/tdefile/kpropertiesdialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tdeio/tdefile/kpropertiesdialog.cpp')
-rw-r--r--tdeio/tdefile/kpropertiesdialog.cpp782
1 files changed, 759 insertions, 23 deletions
diff --git a/tdeio/tdefile/kpropertiesdialog.cpp b/tdeio/tdefile/kpropertiesdialog.cpp
index c8e324a2d..1096d871d 100644
--- a/tdeio/tdefile/kpropertiesdialog.cpp
+++ b/tdeio/tdefile/kpropertiesdialog.cpp
@@ -124,6 +124,9 @@ extern "C" {
#include <krun.h>
#include <tdelistview.h>
#include <kacl.h>
+#include <kprotocolinfo.h>
+#include <ktabwidget.h>
+#include <tdeaccel.h>
#include "tdefilesharedlg.h"
#include "kpropertiesdesktopbase.h"
@@ -139,6 +142,17 @@ extern "C" {
# include <win32_utils.h>
#endif
+// This KDE3-era HACK ensures that TDEIO jobs are properly terminated in the
+// applyChanges() slots.
+void tqt_enter_modal( TQWidget *widget );
+void tqt_leave_modal( TQWidget *widget );
+#define WAIT_FOR_JOB \
+ TQWidget dummy(0,0,(WFlags)(WType_Dialog|WShowModal)); \
+ tqt_enter_modal(&dummy); \
+ tqApp->enter_loop(); \
+ tqt_leave_modal(&dummy);
+#define JOB_DONE tqApp->exit_loop();
+
static TQString nameFromFileName(TQString nameStr)
{
if ( nameStr.endsWith(".desktop") )
@@ -387,6 +401,7 @@ bool KPropertiesDialog::canDisplay( KFileItemList _items )
KBindingPropsPlugin::supports( _items ) ||
KURLPropsPlugin::supports( _items ) ||
KDevicePropsPlugin::supports( _items ) ||
+ TDEAttrPropsPlugin::supports(_items) ||
KFileMetaPropsPlugin::supports( _items ) ||
KPreviewPropsPlugin::supports( _items );
}
@@ -486,6 +501,12 @@ void KPropertiesDialog::insertPages()
insertPlugin (p);
}
+ if (TDEAttrPropsPlugin::supports(m_items))
+ {
+ TDEAttrPropsPlugin *p = new TDEAttrPropsPlugin(this);
+ insertPlugin(p);
+ }
+
if ( KFileMetaPropsPlugin::supports( m_items ) )
{
KPropsDlgPlugin *p = new KFileMetaPropsPlugin( this );
@@ -1324,10 +1345,6 @@ bool KFilePropsPlugin::supports( KFileItemList /*_items*/ )
return true;
}
-// Don't do this at home
-void tqt_enter_modal( TQWidget *widget );
-void tqt_leave_modal( TQWidget *widget );
-
void KFilePropsPlugin::applyChanges()
{
if ( d->dirSizeJob ) {
@@ -1383,11 +1400,7 @@ void KFilePropsPlugin::applyChanges()
TQ_SLOT( slotCopyFinished( TDEIO::Job * ) ) );
connect( job, TQ_SIGNAL( renamed( TDEIO::Job *, const KURL &, const KURL & ) ),
TQ_SLOT( slotFileRenamed( TDEIO::Job *, const KURL &, const KURL & ) ) );
- // wait for job
- TQWidget dummy(0,0,(WFlags)(WType_Dialog|WShowModal));
- tqt_enter_modal(&dummy);
- tqApp->enter_loop();
- tqt_leave_modal(&dummy);
+ WAIT_FOR_JOB;
return;
}
properties->updateUrl(properties->kurl());
@@ -1406,8 +1419,7 @@ void KFilePropsPlugin::slotCopyFinished( TDEIO::Job * job )
kdDebug(250) << "KFilePropsPlugin::slotCopyFinished" << endl;
if (job)
{
- // allow apply() to return
- tqApp->exit_loop();
+ JOB_DONE;
if ( job->error() )
{
job->showErrorDialog( d->m_frame );
@@ -2555,11 +2567,7 @@ void KFilePermissionsPropsPlugin::applyChanges()
connect( job, TQ_SIGNAL( result( TDEIO::Job * ) ),
TQ_SLOT( slotChmodResult( TDEIO::Job * ) ) );
- // Wait for job
- TQWidget dummy(0,0,(WFlags)(WType_Dialog|WShowModal));
- tqt_enter_modal(&dummy);
- tqApp->enter_loop();
- tqt_leave_modal(&dummy);
+ WAIT_FOR_JOB;
}
if (dirs.count() > 0) {
job = TDEIO::chmod( dirs, orDirPermissions, ~andDirPermissions,
@@ -2571,11 +2579,7 @@ void KFilePermissionsPropsPlugin::applyChanges()
connect( job, TQ_SIGNAL( result( TDEIO::Job * ) ),
TQ_SLOT( slotChmodResult( TDEIO::Job * ) ) );
- // Wait for job
- TQWidget dummy(0,0,(WFlags)(WType_Dialog|WShowModal));
- tqt_enter_modal(&dummy);
- tqApp->enter_loop();
- tqt_leave_modal(&dummy);
+ WAIT_FOR_JOB;
}
}
@@ -2584,8 +2588,7 @@ void KFilePermissionsPropsPlugin::slotChmodResult( TDEIO::Job * job )
kdDebug(250) << "KFilePermissionsPropsPlugin::slotChmodResult" << endl;
if (job->error())
job->showErrorDialog( d->m_frame );
- // allow apply() to return
- tqApp->exit_loop();
+ JOB_DONE
}
@@ -2863,6 +2866,739 @@ void KBindingPropsPlugin::applyChanges()
/* ----------------------------------------------------
*
+ * TDEAttrPropsPlugin
+ *
+ * -------------------------------------------------- */
+class TDEAttrPropsPlugin::TDEAttrEntry : public TQHBox
+{
+ friend class TDEAttrPropsPlugin;
+ public:
+ TDEAttrEntry(TQWidget *parent)
+ : TQHBox(parent, "tdeattrentry")
+ {
+ m_combo = new TQComboBox(this);
+ m_combo->setEditable(true);
+ m_combo->setDuplicatesEnabled(false);
+ m_combo->lineEdit()->setMaxLength(255);
+ m_combo->setSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed);
+
+ m_value = new TQLineEdit(this);
+ m_value->setMaxLength(255);
+ m_value->setSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed);
+
+ m_delete = new TQPushButton(this);
+ m_delete->setPixmap(SmallIcon("edittrash"));
+ m_delete->setFocusPolicy(TQWidget::NoFocus);
+ m_delete->setSizePolicy(TQSizePolicy::Maximum, TQSizePolicy::Expanding);
+
+ setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ }
+
+ TQCString key() { return m_combo->currentText().local8Bit(); }
+ void setKey(const TQCString& key)
+ {
+ m_combo->setCurrentText(TQString::fromLocal8Bit(key));
+ }
+
+ TQCString value() { return m_value->text().local8Bit(); }
+ void setValue(const TQCString& value)
+ {
+ m_value->setText(TQString::fromLocal8Bit(value));
+ }
+
+ void setReadOnly(bool ro)
+ {
+ m_combo->setDisabled(ro);
+ m_value->setReadOnly(ro);
+ m_delete->setDisabled(ro);
+ }
+
+ ~TDEAttrEntry() {}
+
+ private:
+ TQComboBox *m_combo;
+ TQLineEdit *m_value;
+ TQPushButton *m_delete;
+};
+
+class TDEAttrPropsPlugin::TDEAttrNamespaceTab : public TQWidget
+{
+ friend class TDEAttrPropsPlugin;
+ public:
+ TDEAttrNamespaceTab(TQWidget *parent, TQCString ns)
+ : TQWidget(parent), m_namespace(ns), m_queryPending(true)
+ {
+ m_layout = new TQVBoxLayout(this);
+ m_entriesLayout = new TQVBoxLayout;
+ m_label = new TQLabel(i18n("Querying attributes..."), this);
+
+ m_layout->setSpacing(KDialog::spacingHint());
+ m_layout->setMargin(KDialog::marginHint());
+
+ m_layout->addWidget(m_label);
+ m_layout->addLayout(m_entriesLayout);
+ m_layout->addStretch();
+
+ // Read saved attributes
+ TDEConfig *config = new TDEConfig("kdeglobals");
+ config->setGroup("TDE Extended Attributes");
+ TQString key = "SavedAttributes_" + ns;
+ m_savedAttrs = config->readListEntry(key);
+
+ m_entryWidgets.setAutoDelete(true);
+ }
+
+ private:
+ bool m_queryPending;
+ TQPtrList<TDEAttrEntry> m_entryWidgets, m_pendingWidgets;
+ TQCString m_namespace;
+ TQVBoxLayout *m_layout, *m_entriesLayout;
+ TQMap<TQCString, TQCString> m_entries;
+ TQLabel *m_label;
+ TQStringList m_savedAttrs;
+};
+
+class TDEAttrPropsPlugin::TDEAttrPropsPluginPrivate
+{
+ public:
+ TDEAttrPropsPluginPrivate() {}
+ ~TDEAttrPropsPluginPrivate() {}
+
+ TQFrame *m_frame, *m_tab;
+ KTabWidget *m_tabWidget;
+ TQMap<TQCString, TDEAttrNamespaceTab*> m_tabs;
+ TQHBox *m_buttonsBox;
+ TQPushButton *m_newEntry, *m_editSavedAttrs, *m_preferences;
+ bool m_showSystemNs;
+ TDEAccel *m_accel;
+};
+
+TDEAttrPropsPlugin::TDEAttrPropsPlugin(KPropertiesDialog *_props)
+ : KPropsDlgPlugin(_props)
+{
+ // Initialise tabs
+ d = new TDEAttrPropsPluginPrivate;
+
+ d->m_frame = properties->addPage(i18n("A&ttributes"));
+
+ d->m_tabWidget = new KTabWidget(d->m_frame);
+ d->m_tabWidget->setTabShape(TQTabWidget::Triangular);
+
+ TDEConfig *config = new TDEConfig("kdeglobals");
+ config->setGroup("TDE Extended Attributes");
+ d->m_showSystemNs = config->readBoolEntry("ShowSystemNs");
+
+ TQTimer::singleShot(0, this, TQ_SLOT(slotUpdateTabs()));
+
+ // Initialise button box
+ d->m_buttonsBox = new TQHBox(d->m_frame);
+ d->m_buttonsBox->setSpacing(KDialog::spacingHint());
+ d->m_buttonsBox->setMargin(KDialog::marginHint());
+
+ d->m_newEntry = new TQPushButton(
+ SmallIcon("add"),
+ i18n("Add attribute"),
+ d->m_buttonsBox
+ );
+
+ if (!KProtocolInfo::supportsWritingAttrs(properties->kurl()))
+ {
+ d->m_newEntry->setEnabled(false);
+ }
+
+ d->m_editSavedAttrs = new TQPushButton(
+ SmallIcon("document-save"),
+ i18n("Common attributes..."),
+ d->m_buttonsBox
+ );
+
+ d->m_preferences = new TQPushButton(
+ SmallIcon("configure"),
+ i18n("Preferences..."),
+ d->m_buttonsBox
+ );
+
+ // Initialise shortcuts
+ d->m_accel = new TDEAccel(d->m_frame);
+ d->m_accel->insert(
+ "add", i18n("Add attribute"),
+ i18n("Add a new attribute entry to the current namespace"),
+ TDEShortcut("Insert"), this, TQ_SLOT(slotAddEntry())
+ );
+ d->m_accel->insert(
+ "del", i18n("Remove attribute"),
+ i18n("Remove currently edited attribute entry"),
+ TDEShortcut("Alt+Delete"), this, TQ_SLOT(slotDelEntry())
+ );
+
+ // Create module layout
+ TQVBoxLayout *layout = new TQVBoxLayout(d->m_frame);
+ layout->addWidget(d->m_tabWidget);
+ layout->addWidget(d->m_buttonsBox);
+
+ // Connect signals
+ connect(d->m_newEntry, TQ_SIGNAL(clicked()), TQ_SLOT(slotAddEntry()));
+ connect(d->m_editSavedAttrs, TQ_SIGNAL(clicked()), TQ_SLOT(slotEditSavedAttrs()));
+ connect(d->m_preferences, TQ_SIGNAL(clicked()), TQ_SLOT(slotPreferences()));
+ connect(this, TQ_SIGNAL(changed()), TQ_SLOT(slotCheckNoAttrs()));
+
+ connect(d->m_tabWidget, TQ_SIGNAL(currentChanged(TQWidget*)),
+ TQ_SLOT(slotTabChanged()));
+}
+
+TDEAttrPropsPlugin::~TDEAttrPropsPlugin()
+{
+ delete d;
+}
+
+void
+TDEAttrPropsPlugin::slotUpdateTabs()
+{
+ TQString tip;
+ tip = i18n(
+ "<qt><b>User attributes</b> may be assigned to files and directories "
+ "for storing arbitrary additional information.</qt>"
+ );
+ updateTab("user", i18n("User"), tip);
+
+#if defined(Q_OS_LINUX)
+ tip = i18n(
+ "<qt><p><b>System attributes</b> are used by the kernel to store "
+ "system objects such as Access Control Lists."
+ "<p>Read and write access permissions to system attributes depend on "
+ "the policy implemented for each system attribute implemented by "
+ "filesystems in the kernel.</qt>"
+ );
+ updateTab("system", i18n("System"), tip);
+
+ tip = i18n(
+ "<qt><p><b>Security attributes</b> are used by kernel security modules "
+ "such as SELinux, and also to implement file capabilities."
+ "<p>Read and write access permissions to security attributes depend on "
+ "the policy implemented for each security attribute by the security "
+ "module. When no security module is loaded, all processes have read "
+ "access to extended security attributes, and write access is limited "
+ "to processes that have the CAP_SYS_ADMIN capability.</qt>"
+ );
+ updateTab("security", i18n("Security"), tip);
+
+ tip = i18n(
+ "<qt><p><b>Trusted attributes</b> are visible and accessible only to "
+ "processes that have the CAP_SYS_ADMIN capability. Attributes in this "
+ "class are used to implement mechanisms in user space (i.e., outside "
+ "the kernel) which keep information in extended attributes to which "
+ "ordinary processes should not have access.</qt>"
+ );
+ updateTab("trusted", i18n("Trusted"), tip);
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
+ // From extattr(9) (FIXME: possibly find a more informative source?)
+ tip = i18n(
+ "<qt><p><b>System attributes</b> are protected such that appropriate "
+ "privilege is required to directly access or manipulate them.</qt>"
+ );
+ updateTab("system", i18n("System"), tip);
+#endif
+
+ d->m_tabWidget->setTabBarHidden(d->m_tabWidget->count() == 1);
+ if (d->m_tabWidget->count() == 1) slotTabChanged();
+}
+
+void
+TDEAttrPropsPlugin::updateTab(TQCString ns, TQString label, TQString tip)
+{
+ if (d->m_tabs.contains(ns))
+ {
+ if (ns != "user" && !d->m_showSystemNs)
+ {
+ d->m_tabWidget->removePage(d->m_tabs[ns]);
+ d->m_tabs.remove(ns);
+ }
+ return;
+ }
+ else
+ {
+ if (ns != "user" && !d->m_showSystemNs)
+ {
+ return;
+ }
+
+ TDEAttrNamespaceTab *tab = new TDEAttrNamespaceTab(d->m_tabWidget, ns);
+ d->m_tabWidget->addTab(tab, label);
+ d->m_tabWidget->setTabToolTip(tab, tip);
+ TQWhatsThis::add(tab, tip);
+ d->m_tabs[ns] = tab;
+ }
+}
+
+TDEAttrPropsPlugin::TDEAttrNamespaceTab*
+TDEAttrPropsPlugin::currentNamespaceTab()
+{
+ return static_cast<TDEAttrNamespaceTab*>(d->m_tabWidget->currentPage());
+}
+
+void TDEAttrPropsPlugin::slotTabChanged()
+{
+ TDEAttrNamespaceTab *tab = currentNamespaceTab();
+ if (!tab->m_queryPending)
+ {
+ return;
+ }
+
+ slotCheckNoAttrs();
+
+ // Query attributes
+ KURL url = properties->kurl();
+ TDEIO::AttributeJob *listJob = TDEIO::listAttr(url, tab->m_namespace, true);
+ connect(listJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ TQ_SLOT(slotListJobResult(TDEIO::Job*)));
+}
+
+TDEAttrPropsPlugin::TDEAttrEntry *
+TDEAttrPropsPlugin::addEntry(TDEAttrNamespaceTab *tab)
+{
+ if (!tab) tab = currentNamespaceTab();
+ Q_ASSERT(tab);
+
+ TDEAttrEntry *entryWidget = new TDEAttrEntry(tab);
+ tab->m_entriesLayout->addWidget(entryWidget);
+
+ tab->m_entryWidgets.append(entryWidget);
+
+ entryWidget->m_combo->insertStringList(tab->m_savedAttrs);
+ entryWidget->m_combo->setCurrentText(TQString::null);
+
+ if (!KProtocolInfo::supportsWritingAttrs(properties->kurl()))
+ {
+ entryWidget->setReadOnly(true);
+ }
+
+ entryWidget->show();
+
+ return entryWidget;
+}
+
+void TDEAttrPropsPlugin::connectEntry(TDEAttrEntry *entry)
+{
+ connect(entry->m_combo, TQ_SIGNAL(textChanged(const TQString&)),
+ this, TQ_SIGNAL(changed()));
+ connect(entry->m_value, TQ_SIGNAL(textChanged(const TQString&)),
+ this, TQ_SIGNAL(changed()));
+ connect(entry->m_delete, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotDelButtonPressed()));
+}
+
+void TDEAttrPropsPlugin::slotAddEntry()
+{
+ if (!KProtocolInfo::supportsWritingAttrs(properties->kurl()))
+ {
+ return;
+ }
+ TDEAttrEntry *entryWidget = addEntry();
+ connectEntry(entryWidget);
+ entryWidget->m_combo->lineEdit()->setFocus();
+ emit changed();
+}
+
+void TDEAttrPropsPlugin::slotDelEntry()
+{
+ TDEAttrNamespaceTab *tab = currentNamespaceTab();
+ if (tab->focusWidget() && tab->focusWidget()->parentWidget())
+ {
+ // From value lineedit
+ TQWidget *w = tab->focusWidget()->parentWidget();
+ if (qstrcmp(w->name(), "tdeattrentry") == 0)
+ {
+ TDEAttrEntry *entry = static_cast<TDEAttrEntry*>(w);
+ delEntry(entry);
+ }
+
+ // From combobox lineedit
+ else if (qstrcmp(w->parentWidget()->name(), "tdeattrentry") == 0)
+ {
+ TDEAttrEntry *entry = static_cast<TDEAttrEntry*>(w->parentWidget());
+ delEntry(entry);
+ }
+ }
+}
+
+void TDEAttrPropsPlugin::slotEditSavedAttrs()
+{
+ TDEAttrNamespaceTab *tab = currentNamespaceTab();
+ TQString caption = i18n("Common attributes [namespace: %1]")
+ .arg(tab->m_namespace);
+
+ KDialogBase *dlg = new KDialogBase(
+ properties,
+ "TDE Saved Attributes",
+ true,
+ caption,
+ KDialogBase::Ok | KDialogBase::Cancel,
+ KDialogBase::Ok
+ );
+
+ KEditListBox *elb = new KEditListBox(dlg);
+ elb->setTitle(caption);
+ elb->insertStringList(currentNamespaceTab()->m_savedAttrs);
+ connect(dlg, TQ_SIGNAL(okClicked()), this, TQ_SLOT(slotApplySavedAttrs()));
+ dlg->setMainWidget(elb);
+ dlg->exec();
+}
+
+void TDEAttrPropsPlugin::slotApplySavedAttrs()
+{
+ KDialogBase *dlg = static_cast<KDialogBase*>(const_cast<TQObject*>(TQObject::sender()));
+ Q_ASSERT(dlg);
+ KEditListBox *elb = static_cast<KEditListBox*>(dlg->mainWidget());
+ Q_ASSERT(elb);
+
+ TDEAttrNamespaceTab *tab = currentNamespaceTab();
+
+ tab->m_savedAttrs = elb->items();
+ TDEConfig *config = new TDEConfig("kdeglobals");
+ config->setGroup("TDE Extended Attributes");
+ TQString key = "SavedAttributes_" + tab->m_namespace;
+ config->writeEntry(key, tab->m_savedAttrs);
+ config->sync();
+ dlg->deleteLater();
+
+ // Update comboboxes immediately
+ TDEAttrEntry *entry;
+ for (entry = tab->m_entryWidgets.first(); entry;
+ entry = tab->m_entryWidgets.next())
+ {
+ TQString currentText = entry->m_combo->currentText();
+ entry->m_combo->clear();
+ entry->m_combo->insertStringList(tab->m_savedAttrs);
+ entry->m_combo->setCurrentText(currentText);
+ }
+}
+
+void
+TDEAttrPropsPlugin::delEntry(TDEAttrPropsPlugin::TDEAttrEntry *entry)
+{
+ if (!KProtocolInfo::supportsWritingAttrs(properties->kurl()))
+ {
+ return;
+ }
+
+ TQCString attr = entry->key();
+ bool del = false;
+
+ if (attr.isEmpty() && entry->value().isEmpty())
+ {
+ del = true;
+ }
+ else
+ {
+ TQString msg;
+ if (!attr.isEmpty())
+ {
+ msg = i18n("<qt>Are you sure you want to delete attribute <b>%1</b>?</qt>")
+ .arg(TQString::fromLocal8Bit(attr));
+ }
+ else
+ {
+ msg = i18n("<qt>Are you sure you want to delete this unnamed attribute?</qt>");
+ }
+
+ int result = KMessageBox::warningYesNo(
+ properties, msg, i18n("Remove attribute?"),
+ KStdGuiItem::yes(), KStdGuiItem::no(), "ConfirmRemoveAttribute");
+ del = (result == KMessageBox::Yes);
+ }
+
+ if (del)
+ {
+ TDEAttrNamespaceTab *tab = static_cast<TDEAttrNamespaceTab*>(entry->parentWidget());
+ Q_ASSERT(tab);
+
+ tab->m_entryWidgets.remove(entry);
+ if (tab->m_entryWidgets.count() > 0)
+ {
+ tab->m_entryWidgets.last()->m_combo->setFocus();
+ }
+ else
+ {
+ tab->setFocus();
+ }
+ emit changed();
+ }
+}
+
+void TDEAttrPropsPlugin::slotDelButtonPressed()
+{
+ const TQObject *sender = TQObject::sender();
+ TQWidget *button = static_cast<TQWidget*>(const_cast<TQObject*>(sender));
+ Q_ASSERT(button);
+ TDEAttrEntry *entry = static_cast<TDEAttrEntry*>(button->parentWidget());
+ Q_ASSERT(entry);
+
+ delEntry(entry);
+}
+
+void TDEAttrPropsPlugin::slotCheckNoAttrs()
+{
+
+ TDEAttrNamespaceTab *tab = currentNamespaceTab();
+ if (tab->m_entryWidgets.count() == 0)
+ {
+ tab->m_label->show();
+ tab->m_label->setText(i18n("No attributes or insufficient permissions."));
+ }
+ else tab->m_label->hide();
+}
+
+void TDEAttrPropsPlugin::slotListJobResult(TDEIO::Job *job)
+{
+ TDEIO::AttributeJob *listJob = static_cast<TDEIO::AttributeJob*>(job);
+ Q_ASSERT(listJob);
+
+ const TQCString& ns = listJob->attributeNs();
+
+ TDEAttrNamespaceTab *tab = d->m_tabs[ns];
+ Q_ASSERT(tab);
+
+ if (job->error())
+ {
+ job->showErrorDialog();
+ tab->m_label->setText(i18n("Error reading attributes information!"));
+ }
+ else
+ {
+ TQValueList<TQCString> attrs = listJob->attributes();
+ TQValueList<TQCString>::iterator it;
+ for (it = attrs.begin(); it != attrs.end(); ++it)
+ {
+ TQCString attr(*it);
+ TDEAttrEntry *entryWidget = addEntry(tab);
+ entryWidget->setKey(attr);
+ tab->m_pendingWidgets.append(entryWidget);
+
+ TDEIO::AttributeJob *readJob = TDEIO::readAttr(properties->kurl(),
+ ns, attr, false);
+ connect(readJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(slotReadJobResult(TDEIO::Job*)));
+ }
+
+ slotCheckNoAttrs();
+ }
+}
+
+void TDEAttrPropsPlugin::slotReadJobResult(TDEIO::Job *job)
+{
+ TDEIO::AttributeJob *readJob = static_cast<TDEIO::AttributeJob*>(job);
+ Q_ASSERT(readJob);
+
+ if (job->error())
+ {
+ job->showErrorDialog();
+ }
+ else
+ {
+ const TQCString& ns = readJob->attributeNs();
+
+ TDEAttrNamespaceTab *tab = d->m_tabs[ns];
+ Q_ASSERT(tab);
+
+ tab->m_queryPending = false;
+
+ const TQCString& attr = readJob->attribute(), val = readJob->value();
+ TDEAttrEntry *entryWidget;
+ for (entryWidget = tab->m_pendingWidgets.first(); entryWidget;
+ entryWidget = tab->m_pendingWidgets.next())
+ {
+ if (entryWidget->key() == attr)
+ {
+ entryWidget->setValue(val);
+ tab->m_pendingWidgets.remove(entryWidget);
+ tab->m_entries[attr] = val;
+ if (KProtocolInfo::supportsWritingAttrs(properties->kurl()))
+ {
+ entryWidget->setReadOnly(false);
+ connectEntry(entryWidget);
+ }
+ tab->m_pendingWidgets.remove(entryWidget);
+ tab->m_entries[attr] = val;
+ return;
+ }
+ }
+
+ kdWarning() << "attribute widget not found: " << ns << "." << attr << endl;
+ }
+}
+
+void TDEAttrPropsPlugin::slotWriteJobResult(TDEIO::Job *job)
+{
+ TDEIO::AttributeJob *writeJob = static_cast<TDEIO::AttributeJob*>(job);
+ Q_ASSERT(writeJob);
+
+ if (job->error())
+ {
+ job->showErrorDialog();
+ }
+ else
+ {
+ TDEAttrNamespaceTab *tab = d->m_tabs[writeJob->attributeNs()];
+ Q_ASSERT(tab);
+ tab->m_entries[writeJob->attribute()] = writeJob->value();
+ }
+ JOB_DONE;
+}
+
+void TDEAttrPropsPlugin::slotRemoveJobResult(TDEIO::Job *job)
+{
+ TDEIO::AttributeJob *removeJob = static_cast<TDEIO::AttributeJob*>(job);
+ Q_ASSERT(removeJob);
+
+ if (job->error())
+ {
+ job->showErrorDialog();
+ }
+ else
+ {
+ TDEAttrNamespaceTab *tab = d->m_tabs[removeJob->attributeNs()];
+ Q_ASSERT(tab);
+ tab->m_entries.remove(removeJob->attribute());
+ }
+ JOB_DONE;
+}
+
+void TDEAttrPropsPlugin::applyChanges()
+{
+ if (!KProtocolInfo::supportsWritingAttrs(properties->kurl()))
+ {
+ return;
+ }
+ TDEIO::AttributeJob *writeJob;
+
+ TQMap<TQCString, TDEAttrNamespaceTab*>::Iterator it;
+ for (it = d->m_tabs.begin(); it != d->m_tabs.end(); ++it)
+ {
+ TDEAttrNamespaceTab *tab = (*it);
+
+ // First do a validation
+ TQStringList existingKeys;
+ TDEAttrEntry *entry;
+ for (entry = tab->m_entryWidgets.first(); entry;
+ entry = tab->m_entryWidgets.next())
+ {
+ if (entry->key().isEmpty() && !entry->value().isEmpty())
+ {
+ KMessageBox::sorry(properties,
+ i18n("There is an attribute without a name."));
+ properties->abortApplying();
+ return;
+ }
+
+ else if (existingKeys.contains(entry->key()))
+ {
+ KMessageBox::sorry(properties,
+ i18n("Duplicate attribute '%1'.")
+ .arg(TQString::fromLocal8Bit(entry->key())));
+ properties->abortApplying();
+ return;
+ }
+
+ existingKeys << entry->key();
+ }
+
+ // Then actually apply the settings
+ for (entry = tab->m_entryWidgets.first(); entry;
+ entry = tab->m_entryWidgets.next())
+ {
+ // Ignore empty fields
+ if (entry->key().isEmpty()) continue;
+
+ // Ignore if the attribute value is unchanged
+ if (tab->m_entries.contains(entry->key()) &&
+ tab->m_entries[entry->key()] == entry->value())
+ {
+ continue;
+ }
+
+ writeJob = TDEIO::writeAttr(properties->kurl(), tab->m_namespace,
+ entry->key(), entry->value(), true);
+ connect(writeJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(slotWriteJobResult(TDEIO::Job*)));
+ WAIT_FOR_JOB;
+ }
+
+ TQMap<TQCString, TQCString> entries(tab->m_entries);
+ TQMap<TQCString, TQCString>::Iterator it;
+ for (it = entries.begin(); it != entries.end(); ++it)
+ {
+ if (!existingKeys.contains(it.key()))
+ {
+ TDEIO::AttributeJob *rmJob = TDEIO::removeAttr(properties->kurl(),
+ tab->m_namespace,
+ it.key(), true);
+ connect(rmJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(slotRemoveJobResult(TDEIO::Job*)));
+ WAIT_FOR_JOB;
+ }
+ }
+ }
+}
+
+void TDEAttrPropsPlugin::slotPreferences()
+{
+ KDialogBase *dlg = new KDialogBase(
+ properties,
+ "TDE Attribute Properties Plugin Preferences",
+ true,
+ i18n("Preferences"),
+ KDialogBase::Ok | KDialogBase::Cancel,
+ KDialogBase::Ok
+ );
+
+ connect(dlg, TQ_SIGNAL(okClicked()), this, TQ_SLOT(slotApplyPreferences()));
+ TQVBox *vbox = dlg->makeVBoxMainWidget();
+
+ TQCheckBox *showSystemNs = new TQCheckBox(
+ i18n("Show &system attributes"),
+ vbox,
+ "showSystemNs"
+ );
+ showSystemNs->setChecked(d->m_showSystemNs);
+
+ dlg->exec();
+}
+
+void TDEAttrPropsPlugin::slotApplyPreferences()
+{
+ KDialogBase *dlg = static_cast<KDialogBase*>(const_cast<TQObject*>(TQObject::sender()));
+ Q_ASSERT(dlg);
+ TQCheckBox *showSystemNs = static_cast<TQCheckBox*>(dlg->child("showSystemNs", "TQCheckBox"));
+ Q_ASSERT(showSystemNs);
+
+ d->m_showSystemNs = showSystemNs->isChecked();
+
+ TDEConfig *config = new TDEConfig("kdeglobals");
+ config->setGroup("TDE Extended Attributes");
+ config->writeEntry("ShowSystemNs", d->m_showSystemNs);
+ config->sync();
+
+ TQTimer::singleShot(0, this, TQ_SLOT(slotUpdateTabs()));
+}
+
+bool TDEAttrPropsPlugin::supports(KFileItemList _items)
+{
+ if (_items.count() != 1)
+ {
+ return false;
+ }
+
+ KFileItem *item = _items.first();
+ if (item->isDir() || !KProtocolInfo::supportsReadingAttrs(item->url()))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/* ----------------------------------------------------
+ *
* KDevicePropsPlugin
*
* -------------------------------------------------- */