summaryrefslogtreecommitdiffstats
path: root/sessionapplet
diff options
context:
space:
mode:
Diffstat (limited to 'sessionapplet')
-rw-r--r--sessionapplet/Makefile.am15
-rw-r--r--sessionapplet/dmctl.cpp322
-rw-r--r--sessionapplet/dmctl.h91
-rw-r--r--sessionapplet/usermanager.cpp281
-rw-r--r--sessionapplet/usermanager.desktop8
-rw-r--r--sessionapplet/usermanager.h78
-rw-r--r--sessionapplet/usermanager.lsm16
7 files changed, 811 insertions, 0 deletions
diff --git a/sessionapplet/Makefile.am b/sessionapplet/Makefile.am
new file mode 100644
index 0000000..4472c36
--- /dev/null
+++ b/sessionapplet/Makefile.am
@@ -0,0 +1,15 @@
+INCLUDES= $(all_includes)
+METASOURCES = AUTO
+
+lib_LTLIBRARIES = usermanager_panelapplet.la
+
+usermanager_panelapplet_la_SOURCES = usermanager.cpp dmctl.cpp
+usermanager_panelapplet_la_LDFLAGS = -module -avoid-version $(all_libraries)
+usermanager_panelapplet_la_LIBADD = $(LIB_KDEUI)
+
+usermanager_DATA = usermanager.desktop
+usermanagerdir = $(kde_datadir)/kicker/applets
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/usermanager.pot
diff --git a/sessionapplet/dmctl.cpp b/sessionapplet/dmctl.cpp
new file mode 100644
index 0000000..a6d5bf9
--- /dev/null
+++ b/sessionapplet/dmctl.cpp
@@ -0,0 +1,322 @@
+/*
+ Copyright (C) 2004 Oswald Buddenhagen <ossi@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the Lesser GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the Lesser GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "dmctl.h"
+
+#ifdef Q_WS_X11
+
+#include <klocale.h>
+#include <dcopclient.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static enum { Dunno, NoDM, NewKDM, OldKDM/*, GDM*/ } DMType = Dunno;
+static const char *ctl, *dpy;
+
+DM::DM() : fd( -1 )
+{
+ char *ptr;
+ struct sockaddr_un sa;
+
+ if (DMType == Dunno) {
+ if (!(dpy = ::getenv( "DISPLAY" )))
+ DMType = NoDM;
+ else if ((ctl = ::getenv( "DM_CONTROL" )))
+ DMType = NewKDM;
+ else if ((ctl = ::getenv( "XDM_MANAGED" )) && ctl[0] == '/')
+ DMType = OldKDM;
+ else
+ DMType = NoDM;
+ }
+ switch (DMType) {
+ default:
+ return;
+ case NewKDM:
+ if ((fd = ::socket( PF_UNIX, SOCK_STREAM, 0 )) < 0)
+ return;
+ sa.sun_family = AF_UNIX;
+ if ((ptr = strchr( dpy, ':' )))
+ ptr = strchr( ptr, '.' );
+ snprintf( sa.sun_path, sizeof(sa.sun_path),
+ "%s/dmctl-%.*s/socket", ctl, ptr ? ptr - dpy : 512, dpy );
+ if (::connect( fd, (struct sockaddr *)&sa, sizeof(sa) )) {
+ ::close( fd );
+ fd = -1;
+ }
+ break;
+ case OldKDM:
+ {
+ QString tf( ctl );
+ tf.truncate( tf.find( ',' ) );
+ fd = ::open( tf.latin1(), O_WRONLY );
+ }
+ break;
+ }
+}
+
+DM::~DM()
+{
+ if (fd >= 0)
+ close( fd );
+}
+
+bool
+DM::exec( const char *cmd )
+{
+ QCString buf;
+
+ return exec( cmd, buf );
+}
+
+/**
+ * Execute a KDM remote control command.
+ * @param cmd the command to execute. FIXME: undocumented yet.
+ * @param ret the result buffer.
+ * @return result:
+ * @li If true, the command was successfully executed.
+ * @p ret might contain addional results.
+ * @li If false and @p ret is empty, a communication error occurred
+ * (most probably KDM is not running).
+ * @li If false and @p ret is non-empty, it contains the error message
+ * from KDM.
+ */
+bool
+DM::exec( const char *cmd, QCString &buf )
+{
+ bool ret = false;
+ int tl;
+ unsigned len = 0;
+
+ if (fd < 0)
+ goto busted;
+
+ if (::write( fd, cmd, (tl = strlen( cmd )) ) != tl) {
+ bust:
+ ::close( fd );
+ fd = -1;
+ busted:
+ buf.resize( 0 );
+ return false;
+ }
+ if (DMType == OldKDM) {
+ buf.resize( 0 );
+ return true;
+ }
+ for (;;) {
+ if (buf.size() < 128)
+ buf.resize( 128 );
+ else if (buf.size() < len * 2)
+ buf.resize( len * 2 );
+ if ((tl = ::read( fd, buf.data() + len, buf.size() - len)) <= 0) {
+ if (tl < 0 && errno == EINTR)
+ continue;
+ goto bust;
+ }
+ len += tl;
+ if (buf[len - 1] == '\n') {
+ buf[len - 1] = 0;
+ if (len > 2 && buf[0] == 'o' && buf[1] == 'k' && buf[2] < 32)
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+}
+
+bool
+DM::canShutdown()
+{
+ if (DMType == OldKDM)
+ return strstr( ctl, ",maysd" ) != 0;
+
+ QCString re;
+
+ return exec( "caps\n", re ) && re.find( "\tshutdown" ) >= 0;
+}
+
+void
+DM::shutdown( KApplication::ShutdownType shutdownType,
+ KApplication::ShutdownMode shutdownMode,
+ const QString &bootOption )
+{
+ if (!bootOption.isEmpty() && DMType != NewKDM)
+ return;
+
+ if (shutdownType != KApplication::ShutdownTypeNone) {
+ QCString cmd( "shutdown\t" );
+ cmd.append( shutdownType == KApplication::ShutdownTypeReboot ?
+ "reboot\t" : "halt\t" );
+ if (!bootOption.isNull())
+ cmd.append( "=" ).append( bootOption.local8Bit() ).append( "\t" );
+ cmd.append( shutdownMode == KApplication::ShutdownModeInteractive ?
+ "ask\n" :
+ shutdownMode == KApplication::ShutdownModeForceNow ?
+ "forcenow\n" :
+ shutdownMode == KApplication::ShutdownModeTryNow ?
+ "trynow\n" : "schedule\n" );
+ exec( cmd.data() );
+ }
+}
+
+bool
+DM::bootOptions( QStringList &opts, int &defopt, int &current )
+{
+ if (DMType != NewKDM)
+ return false;
+
+ QCString re;
+ if (!exec( "listbootoptions\n", re ))
+ return false;
+
+ opts = QStringList::split( '\t', QString::fromLocal8Bit( re.data() ) );
+ if (opts.size() < 4)
+ return false;
+
+ bool ok;
+ defopt = opts[2].toInt( &ok );
+ if (!ok)
+ return false;
+ current = opts[3].toInt( &ok );
+ if (!ok)
+ return false;
+
+ opts = QStringList::split( ' ', opts[1] );
+ for (QStringList::Iterator it = opts.begin(); it != opts.end(); ++it)
+ (*it).replace( "\\s", " " );
+
+ return true;
+}
+
+void
+DM::setLock( bool on )
+{
+ exec( on ? "lock\n" : "unlock\n" );
+}
+
+bool
+DM::isSwitchable()
+{
+ if (DMType == OldKDM)
+ return dpy[0] == ':';
+
+ QCString re;
+
+ return exec( "caps\n", re ) && re.find( "\tlocal" ) >= 0;
+}
+
+int
+DM::numReserve()
+{
+ if (DMType == OldKDM)
+ return strstr( ctl, ",rsvd" ) ? 1 : -1;
+
+ QCString re;
+ int p;
+
+ if (!(exec( "caps\n", re ) && (p = re.find( "\treserve " )) >= 0))
+ return -1;
+ return atoi( re.data() + p + 9 );
+}
+
+void
+DM::startReserve()
+{
+ exec("reserve\n");
+}
+
+bool
+DM::localSessions( SessList &list )
+{
+ if (DMType == OldKDM)
+ return false;
+
+ QCString re;
+
+ if (!exec( "list\talllocal\n", re ))
+ return false;
+ QStringList sess = QStringList::split( QChar('\t'), re.data() + 3 );
+ for (QStringList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
+ QStringList ts = QStringList::split( QChar(','), *it, true );
+ SessEnt se;
+ se.display = ts[0];
+ if (ts[1][0] == '@')
+ se.from = ts[1].mid( 1 ), se.vt = 0;
+ else
+ se.vt = ts[1].mid( 2 ).toInt();
+ se.user = ts[2];
+ se.session = ts[3];
+ se.self = (ts[4].find( '*' ) >= 0);
+ se.tty = (ts[4].find( 't' ) >= 0);
+ list.append( se );
+ }
+ return true;
+}
+
+void
+DM::sess2Str2( const SessEnt &se, QString &user, QString &loc )
+{
+ if (se.tty) {
+ user = i18n("user: ...", "%1: TTY login").arg( se.user );
+ loc = se.vt ? QString("vt%1").arg( se.vt ) : se.display ;
+ } else {
+ user =
+ se.user.isEmpty() ?
+ se.session.isEmpty() ?
+ i18n("Unused") :
+ se.session == "<remote>" ?
+ i18n("X login on remote host") :
+ i18n("... host", "X login on %1").arg( se.session ) :
+ i18n("user: session type", "%1: %2")
+ .arg( se.user ).arg( se.session );
+ loc =
+ se.vt ?
+ QString("%1, vt%2").arg( se.display ).arg( se.vt ) :
+ se.display;
+ }
+}
+
+QString
+DM::sess2Str( const SessEnt &se )
+{
+ QString user, loc;
+
+ sess2Str2( se, user, loc );
+ return i18n("session (location)", "%1 (%2)").arg( user ).arg( loc );
+}
+
+bool
+DM::switchVT( int vt )
+{
+ return exec( QString("activate\tvt%1\n").arg(vt).latin1() );
+}
+
+void
+DM::lockSwitchVT( int vt )
+{
+ if (switchVT( vt ))
+ kapp->dcopClient()->send( "kdesktop", "KScreensaverIface", "lock()", "" );
+}
+
+#endif // Q_WS_X11
diff --git a/sessionapplet/dmctl.h b/sessionapplet/dmctl.h
new file mode 100644
index 0000000..bc58fcb
--- /dev/null
+++ b/sessionapplet/dmctl.h
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 2004,2005 Oswald Buddenhagen <ossi@kde.org>
+ Copyright (C) 2005 Stephan Kulow <coolo@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the Lesser GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the Lesser GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef DMCTL_H
+#define DMCTL_H
+
+#include <kapplication.h>
+
+struct SessEnt {
+ QString display, from, user, session;
+ int vt;
+ bool self:1, tty:1;
+};
+
+typedef QValueList<SessEnt> SessList;
+
+class DM {
+
+#ifdef Q_WS_X11
+
+public:
+ DM();
+ ~DM();
+
+ bool canShutdown();
+ void shutdown( KApplication::ShutdownType shutdownType,
+ KApplication::ShutdownMode shutdownMode,
+ const QString &bootOption = QString::null );
+
+ void setLock( bool on );
+
+ bool isSwitchable();
+ int numReserve();
+ void startReserve();
+ bool localSessions( SessList &list );
+ bool switchVT( int vt );
+ void lockSwitchVT( int vt );
+
+ bool bootOptions( QStringList &opts, int &dflt, int &curr );
+
+ static QString sess2Str( const SessEnt &se );
+ static void sess2Str2( const SessEnt &se, QString &user, QString &loc );
+
+private:
+ int fd;
+
+ bool exec( const char *cmd, QCString &ret );
+ bool exec( const char *cmd );
+
+#else // Q_WS_X11
+
+public:
+ DM() {}
+
+ bool canShutdown() { return false; }
+ void shutdown( KApplication::ShutdownType shutdownType,
+ KApplication::ShutdownMode shutdownMode,
+ const QString &bootOption = QString::null ) {}
+
+ void setLock( bool ) {}
+
+ bool isSwitchable() { return false; }
+ int numReserve() { return -1; }
+ void startReserve() {}
+ bool localSessions( SessList &list ) { return false; }
+ void switchVT( int vt ) {}
+
+ bool bootOptions( QStringList &opts, int &dflt, int &curr );
+
+#endif // Q_WS_X11
+
+}; // class DM
+
+#endif // DMCTL_H
diff --git a/sessionapplet/usermanager.cpp b/sessionapplet/usermanager.cpp
new file mode 100644
index 0000000..faf491f
--- /dev/null
+++ b/sessionapplet/usermanager.cpp
@@ -0,0 +1,281 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Thomas Lübking *
+ * thomas.luebking@web.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <stdlib.h>
+#include <kmenubar.h>
+// #include <qlabel.h>
+#include <qlayout.h>
+#include <qpopupmenu.h>
+#include <dcopclient.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <ksimpleconfig.h>
+#include <kapplication.h>
+#include <kdeversion.h>
+#include <kmessagebox.h>
+#include <kservice.h>
+#include <kstandarddirs.h>
+#include "dmctl.h"
+#include "usermanager.h"
+
+#define _ICONSET_(i) KGlobal::iconLoader()->loadIconSet(i, KIcon::Small, 0, false)
+
+
+UserManager::UserManager(const QString& configFile, Type type, int actions, QWidget *parent, const char *name)
+ : KPanelApplet(configFile, type, actions, parent, name)
+{
+
+ // Get the current application configuration handle
+ ksConfig = config();
+ lockIcon = _ICONSET_("lock");
+ fileSaveIcon = _ICONSET_("filesave");
+ exitIcon = _ICONSET_("exit");
+ setFixedWidth(600);
+
+ menu = new KMenuBar(this);
+ menu->setTopLevelMenu(false);
+ menu->setFrameShape ( QFrame::NoFrame );
+ menu->setMargin ( 0 );
+ menu->setLineWidth ( 0 );
+
+ // sessions
+ sessionPopup = new QPopupMenu(this);
+ menu->insertItem ( getenv("USER"), sessionPopup, 0);
+ connect( sessionPopup, SIGNAL(aboutToShow()), SLOT(slotPopulateSessions()) );
+ connect( sessionPopup, SIGNAL(activated(int)), SLOT(slotSessionActivated(int)) );
+
+ // languages
+ langPopup = new QPopupMenu(this);
+
+ KConfigBase *config = KGlobal::config();
+ config->setGroup("Locale");
+ langList = config->readListEntry ("Language", ':');
+// QString flag( locate( "locale", QString::fromLatin1( "l10n/%1/flag.png" ).arg(langList[0]) ) );
+// langLabel = new QLabel(this);
+// langLabel->setPixmap(_ICONSET_(flag).pixmap());
+
+ menu->insertItem ( '[' + langList[0].section('_',0,0) + ']', langPopup, 1 );
+ menu->connectItem ( 1, this, SLOT(slotPopulateLanguages()) );
+ connect( langPopup, SIGNAL(aboutToShow()), SLOT(slotPopulateLanguages()) );
+ connect( langPopup, SIGNAL(activated(int)), SLOT(slotLanguageActivated(int)) );
+
+ menu->adjustSize();
+
+ setFixedWidth(menu->width()+5);
+
+ mainView = menu;
+ menu->move(menu->mapToParent(QPoint(0,0)).x(),0);
+ menu->show();
+}
+
+UserManager::~UserManager()
+{
+}
+
+int UserManager::widthForHeight(int) const
+{
+ return menu->width();
+}
+
+int UserManager::heightForWidth(int) const
+{
+ return menu->height();
+}
+
+void UserManager::about()
+{
+ KMessageBox::information(0, i18n("This is an about box"));
+}
+
+void UserManager::lock()
+{
+ QCString appname( "kdesktop" );
+// if ( kicker_screen_number )
+// appname.sprintf("kdesktop-screen-%d", kicker_screen_number);
+ kapp->dcopClient()->send(appname, "KScreensaverIface", "lock()", "");
+}
+
+void UserManager::logout()
+{
+ kapp->requestShutDown();
+}
+
+
+void UserManager::slotPopulateLanguages()
+{
+ langPopup->clear();
+ KConfig *config = new KConfig("kdeglobals");
+ config->setGroup("Locale");
+ langList = config->readListEntry ("Language", ':');
+ int i = 0;
+ for ( QStringList::ConstIterator it = langList.begin();
+ it != langList.end(); ++it )
+ {
+ KConfig entry(locate( "locale", QString::fromLatin1( "%1/entry.desktop" ).arg(*it) ));
+ entry.setGroup("KCM Locale");
+ QString name = entry.readEntry("Name", i18n("without name"));
+
+ QString flag( locate( "locale", QString::fromLatin1( "%1/flag.png" ).arg(*it) ) );
+ langPopup->insertItem( _ICONSET_(flag), name, i );
+ i++;
+ }
+// langPopup->popup(langLabel->mapToGlobal(QPoint(0,height())));
+}
+
+void UserManager::slotLanguageActivated( int i )
+{
+ if (i == 0)
+ return; // no change, no action
+ menu->changeItem ( 1, '[' + langList[i].section('_',0,0) + ']'/**langPopup->pixmap(i)*/ );
+// langLabel->setPixmap(*langPopup->pixmap(i));
+ KConfig *config = new KConfig("kdeglobals");
+ config->setGroup("Locale");
+ QString tmp = langList[i];
+ langList.remove(langList.at(i));
+ langList.prepend(tmp);
+ config->writeEntry ("Language", langList, ':');
+ config->sync();
+// KService::rebuildKSycoca(this);
+ delete config;
+}
+
+void UserManager::slotPopulateSessions()
+{
+ int p = 0;
+ DM dm;
+
+ sessionPopup->clear();
+ // lock
+ if (kapp->authorize("lock_screen"))
+ {
+ sessionPopup->insertItem(lockIcon, i18n("Lock Session"), 102);
+ }
+ sessionPopup->insertSeparator();
+ // switch
+ if (kapp->authorize("start_new_session") && (p = dm.numReserve()) >= 0)
+ {
+ if (kapp->authorize("lock_screen"))
+ sessionPopup->insertItem(/*_ICONSET_("lockfork"),*/ i18n("Lock&&Load Session..."), 100 );
+ sessionPopup->insertItem(_ICONSET_("fork"), i18n("New Session..."), 101 );
+ if (!p) {
+ sessionPopup->setItemEnabled( 100, false );
+ sessionPopup->setItemEnabled( 101, false );
+ }
+ sessionPopup->insertSeparator();
+ }
+ SessList sess;
+ if (dm.localSessions( sess ))
+ for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
+ int id = sessionPopup->insertItem( DM::sess2Str( *it ), (*it).vt );
+ if (!(*it).vt)
+ sessionPopup->setItemEnabled( id, false );
+ if ((*it).self)
+ sessionPopup->setItemChecked( id, true );
+ }
+ // save
+ sessionPopup->insertSeparator();
+ KConfig ksmserver("ksmserverrc", false, false);
+ ksmserver.setGroup("General");
+ if (ksmserver.readEntry( "loginMode" ) == "restoreSavedSession")
+ {
+ sessionPopup->insertItem(fileSaveIcon, i18n("Save Session"), 103);
+ }
+ // logout
+ if (kapp->authorize("logout"))
+ {
+ sessionPopup->insertItem(exitIcon, i18n("Log Out..."), 104);
+ }
+}
+
+void UserManager::slotSessionActivated( int ent )
+{
+ switch (ent)
+ {
+ case 100:
+ doNewSession( true );
+ break;
+ case 101:
+ doNewSession( false );
+ break;
+ case 102:
+ lock();
+ break;
+ case 103:
+ saveSession();
+ break;
+ case 104:
+ logout();
+ break;
+ default:
+ if (!sessionPopup->isItemChecked( ent ))
+ DM().lockSwitchVT( ent );
+ }
+}
+
+void UserManager::doNewSession( bool lock_ )
+{
+ int result = KMessageBox::warningContinueCancel(
+ kapp->desktop()->screen(kapp->desktop()->screenNumber(this)),
+ i18n("<p>You have chosen to open another desktop session.<br>"
+ "The current session will be hidden "
+ "and a new login screen will be displayed.<br>"
+ "An F-key is assigned to each session; "
+ "F%1 is usually assigned to the first session, "
+ "F%2 to the second session and so on. "
+ "You can switch between sessions by pressing "
+ "Ctrl, Alt and the appropriate F-key at the same time. "
+ "Additionally, the KDE Panel and Desktop menus have "
+ "actions for switching between sessions.</p>")
+ .arg(7).arg(8),
+ i18n("Warning - New Session"),
+ KGuiItem(i18n("&Start New Session"), "fork"),
+ ":confirmNewSession",
+#if KDE_IS_VERSION(3,4,0) //3.4
+ KMessageBox::PlainCaption |
+#endif
+ KMessageBox::Notify);
+
+ if (result==KMessageBox::Cancel)
+ return;
+
+ if (lock_)
+ lock();
+
+ DM().startReserve();
+}
+
+void UserManager::saveSession()
+{
+ QByteArray data;
+ kapp->dcopClient()->send( "ksmserver", "default",
+ "saveCurrentSession()", data );
+}
+
+
+extern "C"
+{
+ KPanelApplet* init( QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("usermanager");
+ return new UserManager(configFile, KPanelApplet::Normal, KPanelApplet::About, parent, "usermanager");
+ }
+}
diff --git a/sessionapplet/usermanager.desktop b/sessionapplet/usermanager.desktop
new file mode 100644
index 0000000..31c61cf
--- /dev/null
+++ b/sessionapplet/usermanager.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Encoding=UTF-8
+Comment=Session Control, Lock, Logout, Change
+Name=SessionManager
+Name[xx]=xxSessionManagerxx
+Icon=fork
+X-KDE-Library=usermanager_panelapplet
+X-KDE-UniqueApplet = true
diff --git a/sessionapplet/usermanager.h b/sessionapplet/usermanager.h
new file mode 100644
index 0000000..87f8864
--- /dev/null
+++ b/sessionapplet/usermanager.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Thomas Lübking *
+ * thomas.luebking@web.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+
+#ifndef USERMANAGER_H
+#define USERMANAGER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kpanelapplet.h>
+#include <qstring.h>
+#include <qiconset.h>
+#include <qstringlist.h>
+#include <kconfig.h>
+
+class KMenuBar;
+class QPopunMenu;
+// class QLabel;
+
+class UserManager : public KPanelApplet
+{
+ Q_OBJECT
+
+public:
+ UserManager(const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+ /** destructor */
+ ~UserManager();
+
+ virtual void about();
+ int heightForWidth(int) const;
+ int widthForHeight(int) const;
+
+protected slots:
+ void slotPopulateSessions();
+ void slotSessionActivated( int );
+ void slotPopulateLanguages();
+ void slotLanguageActivated( int );
+
+protected:
+ void lock();
+ void logout();
+ void saveSession();
+ void doNewSession(bool lock_);
+
+private:
+ KConfig *ksConfig;
+ QWidget *mainView;
+ KMenuBar *menu;
+ QPopupMenu *sessionPopup;
+ QPopupMenu *langPopup;
+ QStringList langList;
+ QIconSet exitIcon;
+ QIconSet lockIcon;
+ QIconSet fileSaveIcon;
+// QLabel *langLabel;
+};
+
+#endif
diff --git a/sessionapplet/usermanager.lsm b/sessionapplet/usermanager.lsm
new file mode 100644
index 0000000..cb6f2cd
--- /dev/null
+++ b/sessionapplet/usermanager.lsm
@@ -0,0 +1,16 @@
+Begin3
+Title: UserManager -- Some description
+Version: 0.1
+Entered-date:
+Description:
+Keywords: KDE Qt
+Author: Thomas Lübking <thomas.luebking@web.de>
+Maintained-by: Thomas Lübking <thomas.luebking@web.de>
+Home-page:
+Alternate-site:
+Primary-site: ftp://ftp.kde.org/pub/kde/unstable/apps/utils
+ xxxxxx usermanager-0.1.tar.gz
+ xxx usermanager-0.1.lsm
+Platform: Linux. Needs KDE
+Copying-policy: GPL
+End