diff --git cmake/modules/KDE4Macros.cmake cmake/modules/KDE4Macros.cmake
index 073d726..ac58d58 100644
--- cmake/modules/KDE4Macros.cmake
+++ cmake/modules/KDE4Macros.cmake
@@ -836,6 +836,10 @@ macro (KDE4_ADD_KDEINIT_EXECUTABLE _target_NAME )
kde4_add_executable(${_target_NAME} "${_nogui}" ${CMAKE_CURRENT_BINARY_DIR}/${_target_NAME}_dummy.cpp ${_resourcefile})
target_link_libraries(${_target_NAME} kdeinit_${_target_NAME})
endif(WIN32)
+ if(_nogui)
+ set_target_properties(kdeinit_${_target_NAME} PROPERTIES COMPILE_FLAGS -DKDE_WITHOUT_GUI)
+ message(STATUS "Building \"kdeinit_${_target_NAME}\" with -DKDE_WITHOUT_GUI because \"${_nogui}\"")
+ endif(_nogui)
endmacro (KDE4_ADD_KDEINIT_EXECUTABLE)
@@ -1010,6 +1014,11 @@ macro (KDE4_ADD_EXECUTABLE _target_NAME)
add_executable(${_target_NAME} ${_add_executable_param} ${_SRCS})
endif (KDE4_ENABLE_FINAL)
+ if(_nogui)
+ set_target_properties(${_target_NAME} PROPERTIES COMPILE_FLAGS -DKDE_WITHOUT_GUI)
+ message(STATUS "Building \"${_target_NAME}\" with -DKDE_WITHOUT_GUI because \"${_nogui}\"")
+ endif(_nogui)
+
IF (KDE4_ENABLE_UAC_MANIFEST)
_kde4_add_manifest(${_target_NAME})
ENDIF(KDE4_ENABLE_UAC_MANIFEST)
diff --git kdeui/actions/kaction.cpp kdeui/actions/kaction.cpp
index 9e8f7fb..54088d2 100644
--- kdeui/actions/kaction.cpp
+++ kdeui/actions/kaction.cpp
@@ -140,6 +140,7 @@ KAction::KAction(QObject *parent)
: QWidgetAction(parent), d(new KActionPrivate)
{
d->init(this);
+ setMenuRole(QAction::NoRole);
}
KAction::KAction(const QString &text, QObject *parent)
@@ -147,6 +148,7 @@ KAction::KAction(const QString &text, QObject *parent)
{
d->init(this);
setText(text);
+ setMenuRole(QAction::NoRole);
}
KAction::KAction(const KIcon &icon, const QString &text, QObject *parent)
@@ -155,6 +157,7 @@ KAction::KAction(const KIcon &icon, const QString &text, QObject *parent)
d->init(this);
setIcon(icon);
setText(text);
+ setMenuRole(QAction::NoRole);
}
KAction::~KAction()
diff --git kdeui/kernel/kapplication.cpp kdeui/kernel/kapplication.cpp
index b093034..ec1455f 100644
--- kdeui/kernel/kapplication.cpp
+++ kdeui/kernel/kapplication.cpp
@@ -138,6 +138,12 @@ static int kde_x_errhandler( Display *dpy, XErrorEvent *err )
void KApplication_init_windows();
#endif
+#ifdef KDE_WITHOUT_GUI
+#define GUIENABLED false
+#else
+#define GUIENABLED true
+#endif //KDE_WITHOUT_GUI
+
/*
Private data to make keeping binary compatibility easier
*/
@@ -205,9 +211,13 @@ public:
void _k_slot_KToolInvocation_hook(QStringList&, QByteArray&);
QString sessionConfigName() const;
- void init(bool GUIenabled=true);
+ void init(bool GUIenabled=GUIENABLED);
void parseCommandLine( ); // Handle KDE arguments (Using KCmdLineArgs)
+#ifdef Q_OS_MAC
+ static void preqapplicationhack(bool GUIenabled = GUIENABLED);
+#else
static void preqapplicationhack();
+#endif
static void preread_app_startup_id();
void read_app_startup_id();
@@ -342,7 +352,11 @@ static SmcConn mySmcConnection = 0;
#endif
KApplication::KApplication(bool GUIenabled)
+#ifdef Q_OS_MAC
+ : QApplication((KApplicationPrivate::preqapplicationhack(GUIenabled),KCmdLineArgs::qtArgc()), KCmdLineArgs::qtArgv(), GUIenabled),
+#else
: QApplication((KApplicationPrivate::preqapplicationhack(),KCmdLineArgs::qtArgc()), KCmdLineArgs::qtArgv(), GUIenabled),
+#endif
d(new KApplicationPrivate(this))
{
d->read_app_startup_id();
diff --git kdeui/kernel/kapplication.h kdeui/kernel/kapplication.h
index fa2ab26..ff17f26 100644
--- kdeui/kernel/kapplication.h
+++ kdeui/kernel/kapplication.h
@@ -97,7 +97,11 @@ public:
*
Call KGlobal::locale(), if using multiple threads.
*
*/
+#ifdef KDE_WITHOUT_GUI
+ explicit KApplication(bool GUIenabled = false);
+#else
explicit KApplication(bool GUIenabled = true);
+#endif // KDE_WITHOUT_GUI
#ifdef Q_WS_X11
/**
@@ -134,8 +138,13 @@ public:
*
* @param GUIenabled Set to false to disable all GUI stuff.
*/
+#ifdef KDE_WITHOUT_GUI
+ KApplication(Display *display, int& argc, char** argv, const QByteArray& rAppName,
+ bool GUIenabled=false);
+#else
KApplication(Display *display, int& argc, char** argv, const QByteArray& rAppName,
bool GUIenabled=true);
+#endif // KDE_WITHOUT_GUI
#endif
virtual ~KApplication();
diff --git kdeui/kernel/kuniqueapplication.h kdeui/kernel/kuniqueapplication.h
index e05dcd7..97fd942 100644
--- kdeui/kernel/kuniqueapplication.h
+++ kdeui/kernel/kuniqueapplication.h
@@ -65,8 +65,13 @@ public:
* depend on the value of the "MultipleInstances"
* key in the "KDE" group of the application config file.
*/
+#ifdef KDE_WITHOUT_GUI
+ explicit KUniqueApplication( bool GUIenabled=false,
+ bool configUnique=false);
+#else
explicit KUniqueApplication( bool GUIenabled=true,
bool configUnique=false);
+#endif //KDE_WITHOUT_GUI
#ifdef Q_WS_X11
/**
diff --git kdeui/notifications/kstatusnotifieritem.cpp kdeui/notifications/kstatusnotifieritem.cpp
index 1b15d40..1ed7de3 100644
--- kdeui/notifications/kstatusnotifieritem.cpp
+++ kdeui/notifications/kstatusnotifieritem.cpp
@@ -683,6 +683,9 @@ bool KStatusNotifierItemPrivate::checkVisibility(QPoint pos, bool perform)
return false;
}
+#else
+ Q_UNUSED(pos);
+ Q_UNUSED(perform);
#endif
return true;
@@ -745,8 +748,20 @@ void KStatusNotifierItemPrivate::init(const QString &extraId)
//create a default menu, just like in KSystemtrayIcon
KMenu *m = new KMenu(associatedWidget);
+#ifdef Q_OS_MAC
+ // emulate addTitle/setTitle by adding an inactive menu item.
+ titleAction = m->addAction( qApp->windowIcon(), KGlobal::mainComponent().aboutData()->programName() );
+ titleAction->setEnabled(false);
+ titleAction->setIconVisibleInMenu(true);
+ m->addAction( titleAction );
+ m->addSeparator();
+ kDebug() << "### Added SystemTray titleAction=" << titleAction;
+ kDebug() << "### SystemTray for app" << qApp << "=" << KGlobal::mainComponent().aboutData()->programName()
+ << "/" << KGlobal::caption() << "with icon" << qApp->windowIcon().name();
+#else
titleAction = m->addTitle(qApp->windowIcon(), KGlobal::caption());
m->setTitle(KGlobal::mainComponent().aboutData()->programName());
+#endif
q->setContextMenu(m);
KStandardAction::quit(q, SLOT(maybeQuit()), actionCollection);
diff --git kdeui/util/kwallet.h kdeui/util/kwallet.h
index d7f703f..895868a 100644
--- kdeui/util/kwallet.h
+++ kdeui/util/kwallet.h
@@ -481,7 +481,6 @@ class KDEUI_EXPORT Wallet : public QObject
* @param success True if the wallet was opened successfully.
*/
void walletOpened(bool success);
-
private Q_SLOTS:
/**
* @internal
diff --git kdeui/util/kwallet_mac.cpp kdeui/util/kwallet_mac.cpp
index 8344ebb..3d9c5a8 100644
--- kdeui/util/kwallet_mac.cpp
+++ kdeui/util/kwallet_mac.cpp
@@ -27,7 +27,9 @@
#include
#include
#include
+#include
#include
+#include
#include
#include
@@ -39,9 +41,16 @@
#include
+#define IDLETIMER_DEBUG
+#undef USE_KWALLETD
+
#include "qosxkeychain.h"
-using namespace KWallet;
+#ifdef USE_KWALLETD
+# include "kwallet_interface.h"
+#endif
+
+#include "kwallet_mac.h"
typedef QMap StringStringMap;
Q_DECLARE_METATYPE(StringStringMap)
@@ -50,7 +59,87 @@ Q_DECLARE_METATYPE(StringToStringStringMapMap)
typedef QMap StringByteArrayMap;
Q_DECLARE_METATYPE(StringByteArrayMap)
-#ifdef OSX_KEYCHAIN_PORT_DISABLED
+#include
+#include
+#include
+#include
+
+static mach_timebase_info_data_t sTimebaseInfo;
+static double calibrator= 0, startTime = 0;
+static QSharedValue sharedStartTime;
+
+double HRTime_Time()
+{
+ return mach_absolute_time() * calibrator - startTime;
+}
+
+void init_HRTime()
+{
+ if( !calibrator ){
+ mach_timebase_info(&sTimebaseInfo);
+ /* go from absolute time units to seconds (the timebase is calibrated in nanoseconds): */
+ calibrator= 1e-9 * sTimebaseInfo.numer / sTimebaseInfo.denom;
+ QString key = "kwalletWallClockStartTime";
+ sharedStartTime.attachOrCreate( key, HRTime_Time() );
+ sharedStartTime.getValue(startTime);
+ qDebug() << "init_HRTime(): connected to kwalletWallClock at t=" << HRTime_Time();
+ }
+}
+
+namespace KWallet
+{
+
+#ifdef USE_KWALLETD
+class KWalletDLauncher
+{
+public:
+ KWalletDLauncher();
+ ~KWalletDLauncher();
+ org::kde::KWallet &getInterface();
+
+ org::kde::KWallet *m_wallet;
+ KConfigGroup m_cgroup;
+};
+
+K_GLOBAL_STATIC(KWalletDLauncher, walletLauncher)
+static const char s_kwalletdServiceName[] = "org.kde.kwalletd";
+
+#else
+
+/**
+ * maps wallet name to a map of app name to instances
+ */
+// deserialising the WalletUsersList from a QDataStream works only for a few WalletInstancePtr types
+// We could store the Wallet* in a QByteArray, but that would make it impossible to dump the WalletUsersList
+// to the console for debugging. So we use a QVariant.
+typedef QVariant WalletInstancePtr;
+// typedef QList > WalletUsersListEntryData;
+class WalletUsersListEntryData : public QList >
+{
+public:
+ static WalletUsersListEntryData create(QPair &head)
+ {
+ WalletUsersListEntryData self;
+ self.clear();
+ self.append(head);
+ return self;
+ }
+ static WalletUsersListEntryData create(QPair head)
+ {
+ WalletUsersListEntryData self;
+ self.clear();
+ self.append(head);
+ return self;
+ }
+};
+
+typedef QMap WalletUsersListEntry;
+typedef QMap WalletUsersList;
+static WalletUsersList walletUsers;
+
+#endif //USE_KWALLETD
+
+
static QString appid()
{
KComponentData cData = KGlobal::mainComponent();
@@ -63,7 +152,6 @@ static QString appid()
}
return qApp->applicationName();
}
-#endif
/*static*/ const QString Wallet::LocalWallet()
{
@@ -104,26 +192,250 @@ static QString appid()
return "Form Data";
}
+#ifndef USE_KWALLETD
+static QStringList getUsersFromRegistry(QString &name)
+{ QString app = appid();
+ QStringList users;
+ users.clear();
+ if( walletUsers.contains(name) ){
+ WalletUsersListEntry entry = walletUsers[name];
+ for( WalletUsersListEntry::const_iterator it = entry.constBegin() ; it != entry.constEnd() ; ++it ){
+ if( !it.value().isEmpty() ){
+ users.append(it.key());
+ }
+ }
+ }
+ return users;
+}
+
+static void removeFromRegistry( QString app, QString &name, WalletUsersListEntryData &entries )
+{
+ for( WalletUsersListEntryData::const_iterator it = entries.constBegin() ; it != entries.constEnd() ; ++it ){
+ QPair wdat = *it;
+ if( walletUsers.contains(name) && walletUsers[name].contains(app) ){
+ WalletUsersListEntry entry = walletUsers[name];
+ WalletUsersListEntryData appInstances = entry[app];
+ if( appInstances.contains(wdat) ){
+ appInstances.removeAll(wdat);
+ qDebug() << "removing application instance" << wdat << "from registry";
+ }
+ if( appInstances.isEmpty() ){
+ entry.remove(app);
+ qDebug() << "removing application" << app << "from registry";
+ }
+ else{
+ entry[app] = appInstances;
+ }
+ if( entry[app].isEmpty() ){
+ walletUsers.remove(name);
+ qDebug() << "removing wallet" << name << "from registry";
+ }
+ else{
+ walletUsers[name] = entry;
+ }
+ }
+ }
+}
+#endif //USE_KWALLETD
+
#pragma mark ==== Wallet::WalletPrivate ====
-class Wallet::WalletPrivate : public OSXKeychain
+Wallet::WalletPrivate::WalletPrivate(Wallet *wallet, const QString &n, int h)
+ : OSXKeychain(n, &isNew), q(wallet), handle(h)
+ , idleTimer(NULL)
+#ifdef IDLETIMER_DEBUG
+ , idleTimerTriggered(0)
+#endif
+ , lastConfigCheckTime(-1)
{
-public:
- explicit WalletPrivate(const QString &n)
- : OSXKeychain(n)
- {
- isKDEChain = ( n == LocalWallet() || n == NetworkWallet() || n.contains( "wallet", Qt::CaseInsensitive ) );
+ isKDEChain = ( n == LocalWallet() || n == NetworkWallet() || n.contains( "wallet", Qt::CaseInsensitive ) );
+ if( !calibrator ){
+ init_HRTime();
+ }
+ if( isKDEChain ){
+ if( !lastAccessTime.attachOrCreate( (QString&)n, QSharedMemory::ReadWrite) ){
+ qDebug() << "Couldn't create shared lastAccessTime member for wallet" << n
+ << "; idle timeouts will be per-client. Error" << lastAccessTime.errorString();
+ }
+ handleIdleTiming(__FUNCTION__);
}
+}
+Wallet::WalletPrivate::~WalletPrivate()
+{
+#ifndef USE_KWALLETD
+ removeFromRegistry();
+#endif //USE_KWALLETD
+ deleteIdleTimer();
+}
- // needed for compilation reasons
- void walletServiceUnregistered()
- {
+#ifndef USE_KWALLETD
+void Wallet::WalletPrivate::addToRegistry()
+{ QString app = appid();
+ QPair wdat = qMakePair(QVariant((qulonglong)q),getpid());
+ if( !walletUsers.contains(name) ){
+ // Unknown wallet name, so there ought not be an existing QMap
+ WalletUsersListEntryData detail;
+ detail.clear();
+ detail.append(wdat);
+ WalletUsersListEntry entry;
+ entry.clear();
+ entry[app] = detail;
+ walletUsers[name] = entry;
}
-};
+ else{
+ WalletUsersListEntry entry = walletUsers[name];
+ WalletUsersListEntryData detail;
+ if( entry.contains(app) ){
+ detail = entry[app];
+ }
+ else{
+ detail.clear();
+ }
+ detail.append(wdat);
+ entry[app] = detail;
+ walletUsers[name] = entry;
+ }
+ QByteArray mapData;
+ QDataStream ds(&mapData, QIODevice::WriteOnly);
+ ds << walletUsers;
+ qDebug() << "@@@" << HRTime_Time() << "Added" << wdat << "for app" << app << "to wallet" << name << "in registry of len=" << mapData.length() << walletUsers;
+}
+
+void Wallet::WalletPrivate::removeFromRegistry()
+{
+ WalletUsersListEntryData entries = WalletUsersListEntryData::create(qMakePair(QVariant((qulonglong)q),getpid()));
+ KWallet::removeFromRegistry( appid(), name, entries );
+}
+
+QStringList Wallet::WalletPrivate::getUsersFromRegistry()
+{
+ return KWallet::getUsersFromRegistry(name);
+}
+#endif //USE_KWALLETD
+
+void Wallet::WalletPrivate::close()
+{
+// // close the keychain wallet but only if we get here through the kwalletmanager
+// // or TODO if wallets should be closed when the last client disconnects
+// // and we are the last client.
+// if( appid() == "KDE Wallet Manager" ){
+ deleteIdleTimer();
+ OSXKeychain::close();
+// }
+}
+
+OSStatus Wallet::WalletPrivate::lock()
+{
+ if( idleTimer ){
+ idleTimer->stop();
+ }
+ return Lock(reference());
+}
+
+void Wallet::WalletPrivate::walletServiceUnregistered()
+{
+#ifdef USE_KWALLETD
+ if( handle >= 0 ){
+ q->slotWalletClosed(handle);
+ }
+#endif
+}
+
+void Wallet::WalletPrivate::deleteIdleTimer()
+{
+ if( idleTimer ){
+ idleTimer->stop();
+ idleTimer->deleteLater();
+ idleTimer = NULL;
+ }
+}
+
+// This function is to be called at every operation that is supposed to launch or reset
+// the idle timing.
+void Wallet::WalletPrivate::handleIdleTiming(const char *caller, bool touchAccessTime)
+{
+ if( !isKDEChain ){
+ return;
+ }
+ double now = HRTime_Time();
+ if( lastConfigCheckTime < 0 || (now - lastConfigCheckTime >= 10) ){
+ lastConfigCheckTime = now;
+ KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
+ if (cfg.readEntry("Close When Idle", true)) {
+ timeOut = cfg.readEntry( "Idle Timeout", ((int)0) );
+ if( caller && idleTimer ){
+ qDebug() << "###" << caller << "->handleIdleTiming: setting" << idleTimer << "for wallet" << name << "handle" << handle << "timeout to" << timeOut;
+ }
+ }
+ else{
+ timeOut = -1;
+ }
+ }
+ if( timeOut >= 0 ){
+ if( !idleTimer ){
+ idleTimer = new QTimer(0);
+ connect( idleTimer, SIGNAL(timeout()), this, SLOT(slotIdleTimedOut()), Qt::DirectConnection );
+ }
+ else{
+ idleTimer->stop();
+ }
+ // when the idle timer fires, the wallet is supposed to be closed. There is thus
+ // no reason to use a repeating timer.
+ idleTimer->setSingleShot(true);
+ if( touchAccessTime ){
+ if( !lastAccessTime.setValue(HRTime_Time()) ){
+ qDebug() << "Cannot set new lastAccessTime for wallet" << name << "error" << lastAccessTime.errorString();
+ }
+ }
+ idleTimer->start( timeOut * 60 * 1000 );
+ }
+ else{
+ timeOut = -1;
+ deleteIdleTimer();
+ }
+}
+
+void Wallet::WalletPrivate::slotIdleTimedOut()
+{ double lastTime = 0;
+ // check the last time anyone accessed this wallet:
+ if( !lastAccessTime.getValue(lastTime) ){
+ qDebug() << "Cannot get lastAccessTime for wallet" << name << "error" << lastAccessTime.errorString();
+ }
+ // the time elapsed since that last access, in minutes:
+ double elapsed = (HRTime_Time() - lastTime) / 60;
+#ifdef IDLETIMER_DEBUG
+ idleTimerTriggered += 1;
+ qDebug() << "###" << HRTime_Time() << appid() << "Idle timeout" << timeOut << "min. for" << q << name << "handle" << handle
+ << "; elapsed minutes=" << elapsed << "timer" << idleTimer << "triggered" << idleTimerTriggered << "times";
+#endif //IDLETIMER_DEBUG
+ if( elapsed >= timeOut ){
+ // we have a true timeout, i.e. we didn't access the wallet in timeOut minutes, and no one else did either.
+ q->slotWalletClosed(handle);
+ }
+ else{
+ // false alarm, reset the timer, but there's no need to count this as an access!
+ handleIdleTiming(__FUNCTION__, false);
+ }
+}
Wallet::Wallet(int handle, const QString& name)
- : QObject(0L), d(new WalletPrivate(name))
+ : QObject(0L), d(new WalletPrivate(this, name, handle))
{
- Q_UNUSED(handle);
+#ifdef USE_KWALLETD
+ QDBusServiceWatcher *watcher = new QDBusServiceWatcher(QString::fromLatin1(s_kwalletdServiceName), QDBusConnection::sessionBus(),
+ QDBusServiceWatcher::WatchForUnregistration, this);
+ connect(watcher, SIGNAL(serviceUnregistered(QString)),
+ d, SLOT(walletServiceUnregistered()));
+
+ connect(&walletLauncher->getInterface(), SIGNAL(walletClosed(int)), SLOT(slotWalletClosed(int)));
+ connect(&walletLauncher->getInterface(), SIGNAL(folderListUpdated(QString)), SLOT(slotFolderListUpdated(QString)));
+ connect(&walletLauncher->getInterface(), SIGNAL(folderUpdated(QString,QString)), SLOT(slotFolderUpdated(QString,QString)));
+ connect(&walletLauncher->getInterface(), SIGNAL(applicationDisconnected(QString,QString)), SLOT(slotApplicationDisconnected(QString,QString)));
+#else
+ d->addToRegistry();
+#endif // USE_KWALLETD
+ if( d->handle != handle ){
+ qDebug() << "Wallet::Wallet(" << name << ") handle changed from" << handle << "to" << d->handle;
+ }
}
Wallet::~Wallet()
@@ -172,6 +484,9 @@ Wallet::~Wallet()
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return walletLauncher->getInterface().isOpen(name); // default is false
#else
+#ifdef USE_KWALLETD
+ walletLauncher->getInterface().isOpen(name);
+#endif // USE_KWALLETD
return OSXKeychain::IsOpen(name);
#endif
}
@@ -181,6 +496,11 @@ bool Wallet::isOpen() const
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return d->handle != -1;
#else
+ d->handleIdleTiming(__FUNCTION__);
+
+#ifdef USE_KWALLETD
+ QDBusReply r = walletLauncher->getInterface().isOpen(d->name);
+#endif // USE_KWALLETD
return d->isOpen();
#endif
}
@@ -193,7 +513,12 @@ bool Wallet::isOpen() const
return r.isValid() ? r : -1;
#else
Q_UNUSED(force);
- return OSXKeychain::Lock(name);
+#ifdef USE_KWALLETD
+ QDBusReply r = walletLauncher->getInterface().close(name, force);
+#endif // USE_KWALLETD
+ // emit a signal that we just closed the wallet
+ Wallet(0, name).slotWalletClosed(0);
+ return OSXKeychain::IsOpen(name);
#endif
}
@@ -213,10 +538,25 @@ bool Wallet::isOpen() const
{
Q_UNUSED(w);
Q_UNUSED(ot);
- Wallet *wallet = new Wallet(-1, name);
- QMetaObject::invokeMethod( wallet, "emitWalletOpened", Qt::QueuedConnection );
- OSStatus err = wallet->d->unLock();
- kDebug() << "Opened wallet '" << name << "': " << wallet << " error=" << err;
+ Wallet *wallet = new Wallet((int)w, name);
+ if( wallet ){
+#ifdef USE_KWALLETD
+ // connect the daemon's opened signal to the slot filtering the
+ // signals we need
+ connect(&walletLauncher->getInterface(), SIGNAL(walletAsyncOpened(int,int)),
+ wallet, SLOT(walletAsyncOpened(int,int)));
+#endif
+ OSStatus err = wallet->d->unLock();
+ if( !err && wallet->d->isKDEChain && wallet->d->isNew ){
+ wallet->d->setLockSettings( false, 0 );
+ }
+ kDebug() << "Opened wallet '" << name << "': " << wallet << " error=" << err;
+#ifdef USE_KWALLETD
+ wallet->emitWalletOpened();
+#else
+ QMetaObject::invokeMethod( wallet, "emitWalletOpened", Qt::QueuedConnection );
+#endif
+ }
return wallet;
}
@@ -226,8 +566,13 @@ bool Wallet::isOpen() const
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return walletLauncher->getInterface().disconnectApplication(wallet, app); // default is false
#else
- kWarning() << "Wallet::disconnectApplication unimplemented, '" << app << "' from '" << wallet << "'";
- return true;
+ kWarning() << "Wallet::disconnectApplication unimplemented, '" << app << "' from '" << wallet << "'"
+#ifdef USE_KWALLETD
+ << walletLauncher->getInterface().disconnectApplication(wallet, app)
+#endif // USE_KWALLETD
+ ;
+ // app disconnect is done/possible only when the app in question closes its wallet.
+ return false;
#endif
}
@@ -237,8 +582,13 @@ bool Wallet::isOpen() const
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return walletLauncher->getInterface().users(name); // default is QStringList()
#else
- kWarning() << "Wallet::users unimplemented, '" << name << "'";
- return QStringList();
+#ifdef USE_KWALLETD
+ QStringList ul = walletLauncher->getInterface().users(name);
+ kWarning() << "Wallet::users unimplemented, '" << name << "'" << ul;
+ return ul;
+#else
+ return KWallet::getUsersFromRegistry((QString&)name);
+#endif // USE_KWALLETD
#endif
}
@@ -250,8 +600,12 @@ int Wallet::sync()
return -1;
}
- walletLauncher->getInterface().sync(d->handle, appid());
#endif
+ d->handleIdleTiming(__FUNCTION__);
+
+#ifdef USE_KWALLETD
+ walletLauncher->getInterface().sync(d->handle, appid());
+#endif // USE_KWALLETD
return 0;
}
@@ -272,13 +626,17 @@ int Wallet::lockWallet()
}
#else
d->currentService.clear();
+ d->handle = -1;
#endif
- return d->lock();
+ d->lock();
+ emit walletClosed();
+ return 1;
}
const QString& Wallet::walletName() const
{
+ d->handleIdleTiming(__FUNCTION__);
return d->name;
}
@@ -295,6 +653,7 @@ void Wallet::requestChangePassword(WId w)
walletLauncher->getInterface().changePassword(d->name, (qlonglong)w, appid());
#else
Q_UNUSED(w);
+ d->handleIdleTiming(__FUNCTION__);
kWarning() << "Wallet::requestChangePassword unimplemented '" << d->name << "'";
#endif
}
@@ -310,9 +669,18 @@ void Wallet::slotWalletClosed(int handle)
emit walletClosed();
}
#else
- Q_UNUSED(handle);
- kWarning() << "Wallet::slotWalletClosed unimplemented '" << d->name << "'";
- d->currentService.clear();
+// kWarning() << "Wallet::slotWalletClosed unimplemented '" << d->name << "'";
+ if( d->handle == handle ){
+ d->handle = -1;
+ d->currentService.clear();
+ kDebug() << "Wallet::slotWalletClosed '" << d->name << "'";
+ // TODO remove ourselves from the WalletUsersList here!
+ d->close();
+ emit walletClosed();
+ }
+ else{
+ qDebug() << "Wallet::slotWalletClosed '" << d->name << "' ignored because handle" << d->handle << "!=" << handle;
+ }
#endif
}
@@ -327,6 +695,7 @@ QStringList Wallet::folderList()
QDBusReply r = walletLauncher->getInterface().folderList(d->handle, appid());
return r;
#else
+ d->handleIdleTiming(__FUNCTION__);
return QStringList(d->folderList());
#endif
}
@@ -342,6 +711,8 @@ QStringList Wallet::entryList()
QDBusReply r = walletLauncher->getInterface().entryList(d->handle, d->folder, appid());
return r;
#else
+ d->handleIdleTiming(__FUNCTION__);
+
QStringList r = QStringList();
d->itemList(r);
return r;
@@ -359,6 +730,7 @@ bool Wallet::hasFolder(const QString& f)
QDBusReply r = walletLauncher->getInterface().hasFolder(d->handle, f, appid());
return r; // default is false
#else
+ d->handleIdleTiming(__FUNCTION__);
d->folderList();
return d->serviceList.contains(f);
#endif
@@ -379,6 +751,7 @@ bool Wallet::createFolder(const QString& f)
return true; // folder already exists
#else
+ d->handleIdleTiming(__FUNCTION__);
return setFolder(f);
#endif
}
@@ -407,6 +780,7 @@ bool Wallet::setFolder(const QString &f)
return rc;
#else
+ d->handleIdleTiming(__FUNCTION__);
// act as if we just changed folders even if we have no such things; the property
// is stored as the ServiceItemAttr (which shows up as the "Where" field in the Keychain Utility).
if( f.size() == 0 ){
@@ -434,6 +808,7 @@ bool Wallet::removeFolder(const QString& f)
return r; // default is false
#else
+ d->handleIdleTiming(__FUNCTION__);
kWarning() << "Wallet::removeFolder unimplemented (returns true) '" << d->name << "'";
if( d->currentService == f ){
d->currentService.clear();
@@ -448,13 +823,16 @@ const QString& Wallet::currentFolder() const
#ifdef OSX_KEYCHAIN_PORT_DISABLED
return d->folder;
#else
+ d->handleIdleTiming(__FUNCTION__);
return d->currentService;
#endif
}
int Wallet::readEntry(const QString &key, QByteArray &value)
-{ OSStatus err = d->readItem( key, &value, NULL );
+{ OSStatus err;
+ d->handleIdleTiming(__FUNCTION__);
+ err = d->readItem( key, &value, NULL );
kDebug() << "Wallet::readEntry '" << key << "' from wallet " << d->name << ", error=" << ((err)? -1 : 0);
return (err)? -1 : 0;
}
@@ -485,6 +863,7 @@ int Wallet::readEntryList(const QString& key, QMap& value)
#else
Q_UNUSED(key);
Q_UNUSED(value);
+ d->handleIdleTiming(__FUNCTION__);
kWarning() << "Wallet::readEntryList unimplemented (returns -1) '" << d->name << "'";
return -1;
#endif
@@ -507,6 +886,7 @@ int Wallet::renameEntry(const QString& oldName, const QString& newName)
return rc;
#else
+ d->handleIdleTiming(__FUNCTION__);
return d->renameItem( oldName, newName );
#endif
}
@@ -514,6 +894,8 @@ int Wallet::renameEntry(const QString& oldName, const QString& newName)
int Wallet::readMap(const QString &key, QMap &value)
{
+ d->handleIdleTiming(__FUNCTION__);
+
QByteArray v;
const int ret = (d->readItem( key, &v, NULL ))? -1 : 0;
if( ret != 0 ){
@@ -560,6 +942,7 @@ int Wallet::readMapList(const QString& key, QMap
#else
Q_UNUSED(key);
Q_UNUSED(value);
+ d->handleIdleTiming(__FUNCTION__);
kWarning() << "Wallet::readMapList unimplemented (returns -1) '" << d->name << "'";
return -1;
#endif
@@ -568,6 +951,8 @@ int Wallet::readMapList(const QString& key, QMap
int Wallet::readPassword(const QString& key, QString& value)
{
+ d->handleIdleTiming(__FUNCTION__);
+
QByteArray ba;
const int ret = (d->readItem( key, &ba, NULL ))? -1 : 0;
if ( ret == 0 ){
@@ -582,18 +967,23 @@ int Wallet::readPasswordList(const QString& key, QMap& value)
{
Q_UNUSED(key);
Q_UNUSED(value);
+ d->handleIdleTiming(__FUNCTION__);
kWarning() << "Wallet::readPasswordList unimplemented (returns -1) '" << d->name << "'";
return -1;
}
int Wallet::writeEntry(const QString& key, const QByteArray& password )
-{ int ret = d->writeItem( key, password );
+{ int ret;
+ d->handleIdleTiming(__FUNCTION__);
+ ret = d->writeItem( key, password );
kDebug() << "wrote entry '" << key << "' to wallet " << d->name << ", error=" << ret;
return ret;
}
int Wallet::writeEntry(const QString& key, const QByteArray& password, EntryType entryType)
{
+ d->handleIdleTiming(__FUNCTION__);
+
OSXKeychain::EntryType entryCode;
switch( entryType ){
case Wallet::Password:
@@ -616,6 +1006,8 @@ int Wallet::writeEntry(const QString& key, const QByteArray& password, EntryType
int Wallet::writeMap(const QString& key, const QMap& value)
{
+ d->handleIdleTiming(__FUNCTION__);
+
QByteArray mapData;
QDataStream ds(&mapData, QIODevice::WriteOnly);
ds << value;
@@ -630,7 +1022,10 @@ int Wallet::writeMap(const QString& key, const QMap& value)
int Wallet::writePassword(const QString &key, const QString& value)
-{ OSXKeychain::EntryType etype = OSXKeychain::Password;
+{ OSXKeychain::EntryType etype;
+
+ d->handleIdleTiming(__FUNCTION__);
+ etype = OSXKeychain::Password;
int ret = d->writeItem( key, value.toUtf8(), &etype );
kDebug() << "wrote password '" << key << "' to wallet " << d->name << ", error=" << ret;
return ret;
@@ -638,13 +1033,19 @@ int Wallet::writePassword(const QString &key, const QString& value)
bool Wallet::hasEntry(const QString &key)
-{ bool ret = d->hasItem( key, NULL );
+{ bool ret;
+
+ d->handleIdleTiming(__FUNCTION__);
+ ret = d->hasItem( key, NULL );
kDebug() << "wallet '" << d->name << "'" << ((ret)? " has" : " does not have") << " entry '" << key << "'";
return ret;
}
int Wallet::removeEntry(const QString& key)
-{ int ret = d->removeItem( key );
+{ int ret;
+
+ d->handleIdleTiming(__FUNCTION__);
+ ret = d->removeItem( key );
kDebug() << "removed entry '" << key << "' from wallet " << d->name << ", error=" << ret;
return ret;
}
@@ -666,6 +1067,8 @@ Wallet::EntryType Wallet::entryType(const QString& key)
return static_cast(rc);
#else
+ d->handleIdleTiming(NULL);
+
// RJVB: a priori, entries are always 'password' on OS X, but since we also do use them for storing
// maps, it may be best to return Wallet::Unknown to leave some uncertainty and not mislead our caller.
OSXKeychain::EntryType etype;
@@ -690,6 +1093,7 @@ Wallet::EntryType Wallet::entryType(const QString& key)
void Wallet::slotFolderUpdated(const QString& wallet, const QString& folder)
{
if (d->name == wallet) {
+ kDebug() << "emit folderUpdated" << folder;
emit folderUpdated(folder);
}
}
@@ -698,6 +1102,7 @@ void Wallet::slotFolderUpdated(const QString& wallet, const QString& folder)
void Wallet::slotFolderListUpdated(const QString& wallet)
{
if (d->name == wallet) {
+ kDebug() << "emit foldeListrUpdated" << wallet;
emit folderListUpdated();
}
}
@@ -705,17 +1110,19 @@ void Wallet::slotFolderListUpdated(const QString& wallet)
void Wallet::slotApplicationDisconnected(const QString& wallet, const QString& application)
{
-#ifdef OSX_KEYCHAIN_PORT_DISABLED
- if (d->handle >= 0
+#ifdef USE_KWALLETD
+ qDebug() << "slotApplicationDisconnected(" << wallet << "," << application << "); handle="
+ << d->handle << "name=" << d->name << "appid=" << appid();
+ if( d->handle >= 0
&& d->name == wallet
- && application == appid()) {
+ && application == appid()
+ ){
slotWalletClosed(d->handle);
}
#else
Q_UNUSED(wallet);
Q_UNUSED(application);
- kWarning() << "Wallet::slotApplicationDisconnected unimplemented '" << d->name << "'";
-#endif
+#endif //USE_KWALLETD
}
void Wallet::walletAsyncOpened(int tId, int handle)
@@ -733,23 +1140,33 @@ void Wallet::walletAsyncOpened(int tId, int handle)
emit walletOpened(handle > 0);
#else
Q_UNUSED(tId);
- Q_UNUSED(handle);
- kWarning() << "Wallet::walletAsyncOpened unimplemented '" << d->name << "'";
+ d->handleIdleTiming(__FUNCTION__);
+#ifdef USE_KWALLETD
+ // disconnect the async signal
+ disconnect(this, SLOT(walletAsyncOpened(int,int)));
+ qDebug() << "walletAsyncOpened: emit walletOpened(true), handle=" << handle;
+ emit walletOpened(true);
+#endif // USE_KWALLETD
+ d->handle = handle;
#endif
}
void Wallet::emitWalletAsyncOpenError()
{
+ d->handleIdleTiming(__FUNCTION__);
+ kDebug() << "emitWalletAsyncOpenError: emit walletOpened(false)";
emit walletOpened(false);
}
void Wallet::emitWalletOpened()
{
- emit walletOpened(true);
+ d->handleIdleTiming(__FUNCTION__);
+ kDebug() << "emitWalletOpened: emit walletOpened(true)";
+ emit walletOpened(true);
}
-bool Wallet::folderDoesNotExist(const QString& wallet, const QString& folder)
+/*static*/ bool Wallet::folderDoesNotExist(const QString& wallet, const QString& folder)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
QDBusReply r = walletLauncher->getInterface().folderDoesNotExist(wallet, folder);
@@ -764,7 +1181,7 @@ bool Wallet::folderDoesNotExist(const QString& wallet, const QString& folder)
}
-bool Wallet::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key)
+/*static*/ bool Wallet::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key)
{
#ifdef OSX_KEYCHAIN_PORT_DISABLED
QDBusReply r = walletLauncher->getInterface().keyDoesNotExist(wallet, folder, key);
@@ -784,7 +1201,8 @@ bool Wallet::keyDoesNotExist(const QString& wallet, const QString& folder, const
void Wallet::slotCollectionStatusChanged(int status)
{
Q_UNUSED(status);
- kWarning() << "Wallet::slotCollectionStatusChanged unimplemented '" << d->name << "' status=" << status;
+ d->handleIdleTiming(__FUNCTION__);
+ kWarning() << "Wallet::slotCollectionStatusChanged unimplemented '" << d->name << "' status=" << status;
}
void Wallet::slotCollectionDeleted()
@@ -795,6 +1213,7 @@ void Wallet::slotCollectionDeleted()
d->currentService.clear();
#endif
kDebug() << "Wallet::slotCollectionDeleted: closing private data '" << d->name;
+ // TODO remove ourselves from the WalletUsersList here!
d->close();
emit walletClosed();
}
@@ -805,4 +1224,51 @@ void Wallet::virtual_hook(int, void*)
//BASE::virtual_hook( id, data );
}
+#ifdef USE_KWALLETD
+KWalletDLauncher::KWalletDLauncher()
+ : m_wallet(0),
+ m_cgroup(KSharedConfig::openConfig("kwalletrc", KConfig::NoGlobals)->group("Wallet"))
+{
+ m_wallet = new org::kde::KWallet(QString::fromLatin1(s_kwalletdServiceName), "/modules/kwalletd", QDBusConnection::sessionBus());
+}
+
+KWalletDLauncher::~KWalletDLauncher()
+{
+ delete m_wallet;
+}
+
+org::kde::KWallet &KWalletDLauncher::getInterface()
+{
+ Q_ASSERT(m_wallet != 0);
+
+ // check if kwalletd is already running
+ if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QString::fromLatin1(s_kwalletdServiceName)))
+ {
+ // not running! check if it is enabled.
+ bool walletEnabled = m_cgroup.readEntry("Enabled", true);
+ if (walletEnabled) {
+ // wallet is enabled! try launching it
+ QString error;
+ int ret = KToolInvocation::startServiceByDesktopPath("kwalletd.desktop", QStringList(), &error);
+ if (ret > 0){
+ kError(285) << "Couldn't start kwalletd: " << error << endl;
+ }
+
+ if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QString::fromLatin1(s_kwalletdServiceName))) {
+ kDebug(285) << "The kwalletd service is still not registered";
+ } else {
+ kDebug(285) << "The kwalletd service has been registered";
+ }
+ } else {
+ kError(285) << "The kwalletd service has been disabled";
+ }
+ }
+
+ return *m_wallet;
+}
+#endif //USE_KWALLETD
+
+} // namespace KWallet
+
+#include "kwallet_mac.moc"
#include "kwallet.moc"
diff --git kdeui/util/qosxkeychain.cpp kdeui/util/qosxkeychain.cpp
index 7cb9a22..708c728 100644
--- kdeui/util/qosxkeychain.cpp
+++ kdeui/util/qosxkeychain.cpp
@@ -161,7 +161,7 @@ OSXKeychain::OSXKeychain()
serviceList.append("");
}
-OSXKeychain::OSXKeychain(const QString &n)
+OSXKeychain::OSXKeychain(const QString &n, bool *isNew)
: name(n)
{ QString errMsg;
OSStatus err = openKeychain( n, &keyChainRef );
@@ -170,6 +170,12 @@ OSXKeychain::OSXKeychain(const QString &n)
kWarning() << "Keychain '" << n << "' does not exist: attempting to create it";
err = SecKeychainCreate( n.toUtf8(), 0, NULL, true, NULL, &keyChainRef );
isKDEChain = true;
+ if( !err && isNew ){
+ *isNew = true;
+ }
+ }
+ else if( !err && isNew ){
+ *isNew = false;
}
if( isError( err, &errMsg ) ){
@@ -197,14 +203,58 @@ OSXKeychain::OSXKeychain(const QString &n)
void OSXKeychain::close()
{
if( keyChainRef ){
+ Lock(keyChainRef);
CFRelease(keyChainRef);
keyChainRef = NULL;
+ serviceList.clear();
}
}
OSXKeychain::~OSXKeychain()
{
- close();
+ if( keyChainRef ){
+ CFRelease(keyChainRef);
+ keyChainRef = NULL;
+ }
+ serviceList.clear();
+}
+
+OSStatus OSXKeychain::lockSettings(int &closeWhenIdle, unsigned int &idleTimeoutMin)
+{ QString errMsg;
+ SecKeychainSettings kcSettings= { SEC_KEYCHAIN_SETTINGS_VERS1, 0, 0, INT_MAX };
+ OSStatus err = SecKeychainCopySettings( keyChainRef, &kcSettings );
+ if( isError( err, &errMsg ) ){
+ kWarning() << "Error getting settings for" << name << err << "=" << qPrintable(errMsg);
+ }
+ else{
+ closeWhenIdle = kcSettings.useLockInterval;
+ idleTimeoutMin = (int)(kcSettings.lockInterval / 60 + 0.5);
+ }
+ return err;
+}
+
+OSStatus OSXKeychain::setLockSettings(int closeWhenIdle, unsigned int idleTimeoutMin)
+{ QString errMsg;
+ SecKeychainSettings kcSettings = { SEC_KEYCHAIN_SETTINGS_VERS1, 0, 0, INT_MAX };
+ OSStatus err;
+
+ // to switch (or keep) off idle timeout locking set useLockInterval=false and lockInterval=INT_MAX
+ // if lockInterval has any other value, SecKeychainSetSettings() will force useLockInterval=true
+ if( closeWhenIdle ){
+ kcSettings.useLockInterval = 1;
+ kcSettings.lockInterval = idleTimeoutMin * 60;
+ }
+ err = SecKeychainSetSettings( keyChainRef, &kcSettings );
+// if( !err ){
+// SecKeychainSettings ks = { SEC_KEYCHAIN_SETTINGS_VERS1, 0, 0, INT_MAX };
+// ks.useLockInterval = !closeWhenIdle;
+// SecKeychainCopySettings( keyChainRef, &ks );
+// qDebug() << "Keychain settings set to useLockInterval=" << ks.useLockInterval << "lockInterval=" << ks.lockInterval;
+// }
+// else{
+// qDebug() << "Error setting keychain settings:" << err;
+// }
+ return err;
}
OSStatus OSXKeychain::renameItem(const QString ¤tKey, const QString &newKey)
@@ -330,7 +380,7 @@ OSStatus OSXKeychain::Lock(const QString &walletName)
OSStatus err = openKeychain( walletName, &keychain );
if( !err && keychain ){
err = Lock(keychain);
- CFRelease(keychain);
+ CFRelease(keychain);
}
return err;
}
@@ -377,7 +427,7 @@ bool OSXKeychain::HasItem(const QString &key,
*errReturn = err;
}
}
- kDebug() << ((found)? "Found" : "Did not find") << "item '" << key << "' in keychain " << (void*) keychain << ", error=" << err << " " << qPrintable(errMsg);
+ kDebug() << "item '" << key << ((found)? "found" : "not found") << "' in keychain " << (void*) keychain << ", error=" << err << " " << qPrintable(errMsg);
return found;
}
diff --git kdeui/util/qosxkeychain.h kdeui/util/qosxkeychain.h
index d0934e6..7370418 100644
--- kdeui/util/qosxkeychain.h
+++ kdeui/util/qosxkeychain.h
@@ -18,6 +18,8 @@
* Boston, MA 02110-1301, USA.
*/
+#ifndef _QOSXKEYCHAIN_H
+
#include
#include
@@ -59,17 +61,23 @@ namespace {
}
static inline QString asQString( CFStringRef sr )
-{ CFIndex len = CFStringGetLength(sr)*2;
- const CPPArrayDeleter buff(new char[len]);
- if( CFStringGetCString( sr, buff.ptr, len, kCFStringEncodingUTF8 ) ){
- return QString::fromUtf8(buff.ptr); //RJVB: use UTF8
- }
- else if( CFStringGetCString( sr, buff.ptr, len, kCFStringEncodingNonLossyASCII ) ){
- return QString::fromLocal8Bit(buff.ptr);
+{
+ if( sr ){
+ CFIndex len = CFStringGetLength(sr)*2;
+ const CPPArrayDeleter buff(new char[len]);
+ if( CFStringGetCString( sr, buff.ptr, len, kCFStringEncodingUTF8 ) ){
+ return QString::fromUtf8(buff.ptr); //RJVB: use UTF8
+ }
+ else if( CFStringGetCString( sr, buff.ptr, len, kCFStringEncodingNonLossyASCII ) ){
+ return QString::fromLocal8Bit(buff.ptr);
+ }
+ else{
+ CFStringGetCString( sr, buff.ptr, len, NULL );
+ return QString::fromLatin1(buff.ptr);
+ }
}
else{
- CFStringGetCString( sr, buff.ptr, len, NULL );
- return QString::fromLatin1(buff.ptr);
+ return QString();
}
}
@@ -87,8 +95,9 @@ static inline bool isError( OSStatus s, QString *errMsg )
return s != 0;
}
-class OSXKeychain
+class OSXKeychain //: protected QObject
{
+// Q_OBJECT
private:
SecKeychainRef keyChainRef;
QString keyChainPath;
@@ -102,7 +111,7 @@ public:
bool isKDEChain;
OSXKeychain();
- OSXKeychain(const QString &name);
+ OSXKeychain(const QString &name, bool *isNew=NULL);
virtual ~OSXKeychain();
inline SecKeychainRef reference()
@@ -119,54 +128,113 @@ public:
}
inline bool isOpen()
{
- return IsOpen(keyChainRef);
+ // we're either a KDE wallet/keychain and we have a valid keyChainRef,
+ // or we're not KDE and IsOpen will return the state of the default
+ // keychain if keyChainRef==NULL.
+ if( !isKDEChain || keyChainRef ){
+ return IsOpen(keyChainRef);
+ }
+ else{
+ return false;
+ }
}
inline OSStatus lock()
{
- return Lock(keyChainRef);
+ if( !isKDEChain || keyChainRef ){
+ return Lock(keyChainRef);
+ }
+ else{
+ return 0;
+ }
}
inline OSStatus unLock()
{
- return UnLock(keyChainRef);
+ if( !isKDEChain || keyChainRef ){
+ return UnLock(keyChainRef);
+ }
+ else{
+ return 0;
+ }
}
- void close();
+ virtual void close();
+ OSStatus lockSettings(int &closeWhenIdle, unsigned int &idleTimeoutMin);
+ OSStatus setLockSettings(int closeWhenIdle, unsigned int idleTimeoutMin);
inline bool hasItem(const QString &key, OSStatus *errReturn, SecKeychainItemRef *itemRef=NULL)
{
- // qDebug() << "OSXKeychain::hasItem(" << key << "): scanning '" << name << "'=" << (void*) keyChainRef;
- return OSXKeychain::HasItem( key, keyChainRef, errReturn, itemRef );
+ if( !isKDEChain || keyChainRef ){
+ return OSXKeychain::HasItem( key, keyChainRef, errReturn, itemRef );
+ }
+ else{
+ return false;
+ }
}
inline OSStatus readItem(const QString &key, QByteArray *value, SecKeychainItemRef *itemRef=NULL)
{
- return ReadItem( key, value, keyChainRef, itemRef, this );
+ if( !isKDEChain || keyChainRef ){
+ return ReadItem( key, value, keyChainRef, itemRef, this );
+ }
+ else{
+ return 0;
+ }
}
inline OSStatus itemType(const QString &key, EntryType *entryType)
{
- return ItemType( key, entryType, keyChainRef );
+ if( !isKDEChain || keyChainRef ){
+ return ItemType( key, entryType, keyChainRef );
+ }
+ else{
+ return 0;
+ }
}
inline OSStatus removeItem(const QString &key)
{
- return RemoveItem( key, keyChainRef );
+ if( !isKDEChain || keyChainRef ){
+ return RemoveItem( key, keyChainRef );
+ }
+ else{
+ return 0;
+ }
}
inline OSStatus writeItem( const QString &key, const QByteArray &value, EntryType *entryType=NULL )
{
- return WriteItem( key, value, keyChainRef, NULL, entryType, this );
+ if( !isKDEChain || keyChainRef ){
+ return WriteItem( key, value, keyChainRef, NULL, entryType, this );
+ }
+ else{
+ return 0;
+ }
}
inline OSStatus writeItem( const QString &key, const QByteArray &value, const QString &comment,
EntryType *entryType=NULL )
{
- return WriteItem( key, value, comment, keyChainRef, entryType, this );
+ if( !isKDEChain || keyChainRef ){
+ return WriteItem( key, value, comment, keyChainRef, entryType, this );
+ }
+ else{
+ return 0;
+ }
}
inline OSStatus itemList( QStringList &keyList )
{
- return ItemList( keyChainRef, keyList, this );
+ if( !isKDEChain || keyChainRef ){
+ return ItemList( keyChainRef, keyList, this );
+ }
+ else{
+ return 0;
+ }
}
inline QStringList folderList()
{
- QStringList r;
- CacheOldValue gFL(generateFolderList, true);
- ItemList( keyChainRef, r, this );
- r.clear();
- return serviceList;
+ if( !isKDEChain || keyChainRef ){
+ QStringList r;
+ CacheOldValue gFL(generateFolderList, true);
+ ItemList( keyChainRef, r, this );
+ r.clear();
+ return serviceList;
+ }
+ else{
+ return QStringList();
+ }
}
OSStatus renameItem(const QString ¤tKey, const QString &newKey);
@@ -197,4 +265,11 @@ public:
static OSStatus ItemList( const SecKeychainRef keychain, QStringList &keyList, OSXKeychain *osxKeyChain=NULL );
static OSStatus Destroy( SecKeychainRef *keychain );
static OSStatus Destroy( const QString &walletName );
+
+// private Q_SLOTS:
+// virtual void slotIdleTimedOut()
+// {}
};
+
+#define _QOSXKEYCHAIN_H
+#endif
\ No newline at end of file
diff --git kdeui/widgets/kmenu.cpp kdeui/widgets/kmenu.cpp
index 7dab149..9b64236 100644
--- kdeui/widgets/kmenu.cpp
+++ kdeui/widgets/kmenu.cpp
@@ -42,6 +42,11 @@
#include
#include
+#ifdef Q_OS_MAC
+#include
+#include
+#endif //Q_OS_MAC
+
static const char KMENU_TITLE[] = "kmenu_title";
class KMenu::KMenuPrivate
@@ -172,25 +177,100 @@ QAction* KMenu::addTitle(const QString &text, QAction* before)
return addTitle(QIcon(), text, before);
}
+#ifdef Q_OS_MAC
+static bool isMenubarMenu(QMenu *m)
+{ bool ret = false;
+ static int level = -1;
+ QList checkList;
+ level += 1;
+ if (m && m->menuAction()) {
+ QAction *mAct = m->menuAction();
+ qDebug() << "##" << level << "isMenubarMenu(" << m << m->title() << ") menuAction=" << mAct << mAct->text();
+ foreach (QWidget *w, mAct->associatedWidgets()) {
+ if (w == m) {
+ goto done;
+ }
+ qDebug() << "###" << level << "associated widget" << w << w->windowTitle() << "parent=" << w->parentWidget();
+ if (QMenuBar *mb = qobject_cast(w)) {
+ qDebug() << "#### widget is QMenuBar" << mb << mb->windowTitle() << "with parent" << mb->parentWidget();
+ ret = true;
+ goto done;
+ }
+ else if (QMenu *mm = qobject_cast(w)) {
+ if (checkList.contains(mm)) {
+ continue;
+ }
+ checkList.append(mm);
+ qDebug() << "####" << level << "widget is QMenu" << mm << mm->title() << "with parent" << mm->parentWidget();
+ if (isMenubarMenu(mm)) {
+ ret = true;
+ goto done;
+ }
+ }
+ }
+ }
+done:;
+ level -= 1;
+ return ret;
+}
+#endif
+
QAction* KMenu::addTitle(const QIcon &icon, const QString &text, QAction* before)
{
- QAction *buttonAction = new QAction(this);
- QFont font = buttonAction->font();
- font.setBold(true);
- buttonAction->setFont(font);
- buttonAction->setText(text);
- buttonAction->setIcon(icon);
-
- QWidgetAction *action = new QWidgetAction(this);
- action->setObjectName(KMENU_TITLE);
- QToolButton *titleButton = new QToolButton(this);
- titleButton->installEventFilter(d); // prevent clicks on the title of the menu
- titleButton->setDefaultAction(buttonAction);
- titleButton->setDown(true); // prevent hover style changes in some styles
- titleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- action->setDefaultWidget(titleButton);
-
- insertAction(before, action);
+#ifdef Q_OS_MAC
+ bool isMacMenuBar = isMenubarMenu(this);
+#else
+ bool isMacMenuBar = false;
+#endif // Q_OS_MAC
+ QAction *action = new QAction(this);
+ action->setText(text);
+ action->setIcon(icon);
+#ifdef Q_OS_MAC
+ if (isMacMenuBar) {
+ action->setEnabled(false);
+ if (before && actions().contains(before)) {
+ QAction *sepLow = new QAction(this);
+ sepLow->setSeparator(true);
+ insertAction(before, sepLow);
+ insertAction(sepLow, action);
+ if (!actions().startsWith(action)) {
+ QAction *sepHigh = new QAction(this);
+ sepHigh->setSeparator(true);
+ insertAction(action,sepHigh);
+ qDebug() << "#### inserted high separator before" << action << action->text() << "before low separator before" << before;
+ }
+ else{
+ qDebug() << "#### inserted" << action << action->text() << "before low separator before" << before;
+ }
+ }
+ else{
+ if (actions().size()) {
+ addSeparator();
+ }
+ addAction(action);
+ addSeparator();
+ qDebug() << "#### appended low separator after" << action << action->text() << "after existing" << actions().size()-2 << "items (before=" << before;
+ }
+ }
+ else
+#endif // Q_OS_MAC
+ {
+ QFont font = action->font();
+ font.setBold(true);
+ action->setFont(font);
+
+ QWidgetAction *styledAction = new QWidgetAction(this);
+ styledAction->setObjectName(KMENU_TITLE);
+ QToolButton *titleButton = new QToolButton(this);
+ titleButton->installEventFilter(d); // prevent clicks on the title of the menu
+ titleButton->setDefaultAction(action);
+ titleButton->setDown(true); // prevent hover style changes in some styles
+ titleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ styledAction->setDefaultWidget(titleButton);
+
+ insertAction(before, styledAction );
+ action = styledAction;
+ }
return action;
}