diff options
145 files changed, 3334 insertions, 251 deletions
diff --git a/kcheckpass/checkpass_pam.c b/kcheckpass/checkpass_pam.c index 6f281165f..44758b696 100644 --- a/kcheckpass/checkpass_pam.c +++ b/kcheckpass/checkpass_pam.c @@ -140,13 +140,16 @@ AuthReturn Authenticate(const char *caller, const char *method, openlog("kcheckpass", LOG_PID, LOG_AUTH); PAM_data.conv = conv; - if (strcmp(method, "classic")) { - sprintf(pservb, "%.31s-%.31s", caller, method); - pam_service = pservb; - } else { + if (!strcmp(method, "classic")) { PAM_data.classic = 1; pam_service = caller; } + else if (!strcmp(method, "pam")) { + pam_service = caller; + } else { + sprintf(pservb, "%.31s-%.31s", caller, method); + pam_service = pservb; + } pam_error = pam_start(pam_service, user, &PAM_conversation, &pamh); if (pam_error != PAM_SUCCESS) return AuthError; diff --git a/kcontrol/background/bgdialog.cpp b/kcontrol/background/bgdialog.cpp index ae76b701a..8294f53a3 100644 --- a/kcontrol/background/bgdialog.cpp +++ b/kcontrol/background/bgdialog.cpp @@ -504,14 +504,23 @@ void BGDialog::loadWallpaperFilesList() { //search for .desktop files before searching for images without .desktop files TQStringList lst = m_pDirs->findAllResources("wallpaper", "*desktop", false, true); TQStringList files; + TQStringList hiddenfiles; for (TQStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) { KSimpleConfig fileConfig(*it); fileConfig.setGroup("Wallpaper"); + int slash = (*it).findRev('/') + 1; + TQString directory = (*it).left(slash); + TQString imageCaption = fileConfig.readEntry("Name"); TQString fileName = fileConfig.readEntry("File"); + if (fileConfig.readBoolEntry("Hidden",false)) { + hiddenfiles.append(directory + fileName); + continue; + } + if (imageCaption.isEmpty()) { imageCaption = fileName; @@ -527,9 +536,8 @@ void BGDialog::loadWallpaperFilesList() { rs = imageCaption + " (" + TQString::number(n) + ')'; lrs = rs.lower(); } - int slash = (*it).findRev('/') + 1; - TQString directory = (*it).left(slash); bool canLoadScaleable = false; + #ifdef HAVE_LIBART canLoadScaleable = true; #endif @@ -543,7 +551,7 @@ void BGDialog::loadWallpaperFilesList() { lst = m_pDirs->findAllResources("wallpaper", "*", false, true); for (TQStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) { - if ( !(*it).endsWith(".desktop") && files.grep(*it).empty() ) { + if ( !(*it).endsWith(".desktop") && files.grep(*it).empty() && hiddenfiles.grep(*it).empty() ) { // First try to see if we have a comment describing the image. If we do // just use the first line of said comment. KFileMetaInfo metaInfo(*it); diff --git a/kcontrol/input/xcursor/themepage.cpp b/kcontrol/input/xcursor/themepage.cpp index 4fb8b8a69..7caf18c3f 100644 --- a/kcontrol/input/xcursor/themepage.cpp +++ b/kcontrol/input/xcursor/themepage.cpp @@ -73,6 +73,13 @@ struct ThemeInfo { }; +static TQString defaultThemeDescription( const TQString& theme ) +{ + if( theme == "redglass" || theme == "whiteglass" || theme == "pseudocore" || theme == "handhelds" ) + return i18n( "XFree theme %1 - incomplete for KDE" ).arg( theme ); + return i18n( "No description available" );; +} + ThemePage::ThemePage( TQWidget* parent, const char* name ) : TQWidget( parent, name ), selectedTheme( NULL ), currentTheme( NULL ) { @@ -333,7 +340,7 @@ void ThemePage::insertTheme( const TQString &path ) // Defaults in case there's no name or comment field. TQString name = dirName; - TQString desc = i18n( "No description available" ); + TQString desc = defaultThemeDescription( name ); TQString sample = "left_ptr"; KSimpleConfig c( path + "/index.theme", true ); // Open read-only @@ -480,7 +487,7 @@ void ThemePage::insertThemes() // Defaults in case there's no index.theme file or it lacks // a name and a comment field. TQString name = *it; - TQString desc = i18n( "No description available" ); + TQString desc = defaultThemeDescription( name ); TQString sample = "left_ptr"; // Parse the index.theme file if the theme has one. diff --git a/kcontrol/kicker/menutab_impl.h b/kcontrol/kicker/menutab_impl.h index 3d0e09748..877e47ffe 100644 --- a/kcontrol/kicker/menutab_impl.h +++ b/kcontrol/kicker/menutab_impl.h @@ -19,6 +19,9 @@ #define __menutab_impl_h__ #include <tqlistview.h> +#include <stdlib.h> + +#include <kpushbutton.h> #include "menutab.h" diff --git a/kcontrol/spellchecking/spellchecking.cpp b/kcontrol/spellchecking/spellchecking.cpp index 6416f9e9c..a7ed79b46 100644 --- a/kcontrol/spellchecking/spellchecking.cpp +++ b/kcontrol/spellchecking/spellchecking.cpp @@ -67,7 +67,7 @@ void KSpellCheckingConfig::defaults() spellConfig->setRunTogether(0); spellConfig->setDictionary(""); spellConfig->setDictFromList(FALSE); - spellConfig->setEncoding (KS_E_ASCII); + spellConfig->setEncoding (KS_E_UTF8); spellConfig->setClient (KS_CLIENT_ISPELL); } diff --git a/kdeeject/kdeeject b/kdeeject/kdeeject index 71079794d..34e61097e 100755 --- a/kdeeject/kdeeject +++ b/kdeeject/kdeeject @@ -4,12 +4,38 @@ # # Copyright GPL v2 by David Faure <[email protected]> # -if test $# -ge 1 -a "$1" != "--help"; then - quiet=0 - if test "$1" = "-q"; then - quiet=1 - shift - fi +quiet=0 +if test "$1" = "-q"; then + quiet=1 + shift +fi + +if test "$1" = "--help"; then + echo "Usage: $0 <name> where name is a device or a mountpoint." + exit 0 +fi + +if test -z "$1"; then + for dev in /dev/cdrom /dev/dvd /dev/dvdram /dev/cdrecorder; do + if test -e $dev; then + lp=`readlink $dev` + if test -n "$lp"; then + device=/dev/$lp + else + device=$dev + fi + break + fi + done +else + device=$1 +fi + +udi=`dcop kded mediamanager properties $device 2>/dev/null | head -n 1 ` +if test -n "$udi"; then + dcop kded mediamanager unmount "$udi" >/dev/null 2>&1 +fi + # Checking for stuff in the PATH is ugly with sh. # I guess this is the reason for making this a kde app... OS=`uname -s` @@ -34,7 +60,5 @@ if test $# -ge 1 -a "$1" != "--help"; then elif test $quiet -eq 0; then kdialog --title "KDE Eject" --error "Eject $1 failed!" fi -else - kdialog --title "KDE Eject" --msgbox "Usage: $0 <name> where name is a device or a mountpoint." -fi + exit 1 diff --git a/kdesktop/KDesktopIface.h b/kdesktop/KDesktopIface.h index 1aa90e538..b966405e4 100644 --- a/kdesktop/KDesktopIface.h +++ b/kdesktop/KDesktopIface.h @@ -107,6 +107,35 @@ k_dcop: * space for desktop icons */ virtual void desktopIconsAreaChanged(const TQRect &area, int screen) = 0; + + /** + * Find the next free place for a not yet existing icon, so it fits + * in the user arrangement. Basicly prepare for icons to be moved in. + * It will try to find a place in the virtual grid near col,row + * where no other icon is. + * + * If you specify -1 for row or column, it will try to find the next + * free room where no other icon follows. E.g. if you specify column + * = -1 and row = 0, kdesktop will find the next vertical placement + * so that the icon appears at the end of the existing icons preferable + * in the first column. If the first column is full, it will find the + * next free room in the second column. + * + * If you specify both column and row, kdesktop won't care for aligning, + * or surrounding icons, but try to find the free place near the given + * grid place (e.g. specify 0,0 to find the nearest place in the left + * upper corner). + */ + virtual TQPoint findPlaceForIcon( int column, int row) = 0; + + /// copy the desktop file in the Desktop and place it at x, y + virtual void addIcon(const TQString &url, int x, int y) = 0; + + /// same with specific destination + virtual void addIcon(const TQString &url, const TQString &dest, int x, int y) = 0; + + /// remove the desktop file (either full path or relative) + virtual void removeIcon(const TQString &dest) = 0; }; #endif diff --git a/kdesktop/Makefile.am b/kdesktop/Makefile.am index fecd9e9c4..5035fe77f 100644 --- a/kdesktop/Makefile.am +++ b/kdesktop/Makefile.am @@ -6,6 +6,8 @@ kdesktop_la_LIBADD = libkdesktopsettings.la $(top_builddir)/libkonq/libkonq.la SUBDIRS = . lock pics patterns programs init kwebdesktop +KDE_OPTIONS = nofinal + ####### Files bin_PROGRAMS = kcheckrunning diff --git a/kdesktop/desktop.cc b/kdesktop/desktop.cc index 54513e962..a05dfcb99 100644 --- a/kdesktop/desktop.cc +++ b/kdesktop/desktop.cc @@ -32,6 +32,9 @@ #include <unistd.h> #include <kcolordrag.h> #include <kurldrag.h> +#include <stdlib.h> +#include <kio/job.h> +#include <tqfile.h> #include <tqdir.h> #include <tqevent.h> @@ -58,6 +61,7 @@ #include <kglobalsettings.h> #include <kpopupmenu.h> #include <kapplication.h> +#include <kdirlister.h> // Create the equivalent of KAccelBase::connectItem // and then remove this include and fix reconnects in initRoot() -- ellis //#include <kaccelbase.h> @@ -986,4 +990,47 @@ bool KDesktop::event(TQEvent * e) return TQWidget::event(e); } +TQPoint KDesktop::findPlaceForIcon( int column, int row ) +{ + if (m_pIconView) + return m_pIconView->findPlaceForIcon(column, row); + else + return TQPoint(-1, -1); +} + +void KDesktop::addIcon(const TQString & _url, int x, int y) +{ + addIcon( _url, KGlobalSettings::desktopPath(), x, y ); +} + +void KDesktop::addIcon(const TQString & _url, const TQString & _dest, int x, int y) +{ + TQString filename = _url.mid(_url.findRev('/') + 1); + + TQValueList<KIO::CopyInfo> files; + KIO::CopyInfo i; + i.uSource = KURL::fromPathOrURL( _url ); + i.uDest = KURL::fromPathOrURL( _dest ); + i.uDest.addPath( filename ); + files.append(i); + if (!TQFile::exists(i.uDest.prettyURL().replace("file://",TQString::null))) { m_pIconView->slotAboutToCreate( TQPoint( x, y ), files ); + KIO::copy( i.uSource, i.uDest, false ); } + +// m_pIconView->addFuturePosition(filename, x, y); + // qDebug("addIcon %s %s %d %d", _url.latin1(), _dest.latin1(), x, y); +// system(TQString("cp \"%1\" \"%2/%3\"").arg(KURL(_url).path()).arg(KURL(_dest).path()).arg(filename).latin1()); +// m_pIconView->update( _dest ); +} + +void KDesktop::removeIcon(const TQString &_url) +{ + if (_url.at(0) != '/') { + qDebug("removeIcon with relative path not supported for now"); + return; + } + unlink(KURL(_url).path().latin1()); + TQString dest = _url.left(_url.findRev('/') + 1); + m_pIconView->update( dest ); +} + #include "desktop.moc" diff --git a/kdesktop/desktop.h b/kdesktop/desktop.h index d8ec12c69..31928e9d4 100644 --- a/kdesktop/desktop.h +++ b/kdesktop/desktop.h @@ -164,6 +164,11 @@ protected: virtual void setIconsEnabled( bool enable ); virtual bool event ( TQEvent * e ); + virtual TQPoint findPlaceForIcon( int column, int row); + virtual void addIcon(const TQString &url, int x, int y); + virtual void addIcon(const TQString &url, const TQString &dest, int x, int y); + virtual void removeIcon(const TQString &url); + private slots: void desktopResized(); diff --git a/kdesktop/kdiconview.cc b/kdesktop/kdiconview.cc index caa68feb9..5762458fd 100644 --- a/kdesktop/kdiconview.cc +++ b/kdesktop/kdiconview.cc @@ -962,6 +962,18 @@ void KDIconView::slotNewItems( const KFileItemList & entries ) kdDebug(1214) << "KDIconView::slotNewItems count=" << entries.count() << endl; KFileItemListIterator it(entries); KFileIVI* fileIVI = 0L; + + if (m_nextItemPos.isNull() && !m_dotDirectory) { + // Not found, we'll need to save the new pos + kdDebug(1214)<<"Neither a drop position stored nor m_dotDirectory set"<<endl; + m_dotDirectory = new KSimpleConfig( dotDirectoryPath(), true ); + // recursion + slotNewItems( entries ); + delete m_dotDirectory; + m_dotDirectory = 0; + return; + } + for (; it.current(); ++it) { KURL url = it.current()->url(); @@ -1026,15 +1038,6 @@ void KDIconView::slotNewItems( const KFileItemList & entries ) kdDebug(1214)<<"Using saved position"<<endl; } } - else - { - // Not found, we'll need to save the new pos - kdDebug(1214)<<"slotNewItems(): New item without position information, try to find a sane location"<<endl; - - moveToFreePosition(fileIVI); - - m_bNeedSave = true; - } } } @@ -1638,6 +1641,98 @@ void KDIconView::moveToFreePosition(TQIconViewItem *item ) } +TQPoint KDIconView::findPlaceForIconCol( int column, int dx, int dy) +{ + if (column < 0) + return TQPoint(); + + TQRect rect; + rect.moveTopLeft( TQPoint(column * dx, 0) ); + rect.setWidth(dx); + rect.setHeight(dy); + + if (rect.right() > viewport()->width()) + return TQPoint(); + + while ( rect.bottom() < viewport()->height() - spacing() ) + { + if ( !isFreePosition(0,rect) ) + rect.moveBy(0, rect.height()); + else + return rect.topLeft(); + } + + return TQPoint(); +} + +TQPoint KDIconView::findPlaceForIconRow( int row, int dx, int dy ) +{ + if (row < 0) + return TQPoint(); + + TQRect rect; + rect.moveTopLeft(TQPoint(0, row * dy)); + rect.setWidth(dx); + rect.setHeight(dy); + + if (rect.bottom() > viewport()->height()) + return TQPoint(); + + while (rect.right() < viewport()->width() - spacing()) + { + if (!isFreePosition(0,rect)) + rect.moveBy(rect.width()+spacing(), 0); + else + return rect.topLeft(); + } + + return TQPoint(); +} + +TQPoint KDIconView::findPlaceForIcon( int column, int row) +{ + int dx = gridXValue(), dy = 0; + TQIconViewItem *item = firstItem(); + for ( ; item; item = item->nextItem() ) { + dx = QMAX( dx, item->width() ); + dy = QMAX( dy, item->height() ); + } + + dx += spacing(); + dy += spacing(); + + if (row == -1) { + int max_cols = viewport()->width() / dx; + int delta = 0; + TQPoint res; + do { + delta++; + res = findPlaceForIconCol(column + (delta / 2) * (-2 * (delta % 2) + 1), + dx, dy); + if (delta / 2 > QMAX(max_cols - column, column)) + return res; + } while (res.isNull()); + return res; + } + + if (column == -1) { + int max_rows = viewport()->height() / dy; + int delta = 0; + TQPoint res; + do { + delta++; + res = findPlaceForIconRow(row + (delta / 2) * (-2 * (delta % 2) + 1), + dx, dy); + if (delta / 2 > QMAX(max_rows - row, row)) + return res; + } while (res.isNull()); + return res; + } + + // very unlikely - if I may add that + return TQPoint(0, 0); +} + void KDIconView::saveIconPositions() { kdDebug(1214) << "KDIconView::saveIconPositions" << endl; @@ -1665,4 +1760,11 @@ void KDIconView::saveIconPositions() m_dotDirectory->sync(); } +void KDIconView::update( const TQString &_url ) +{ + if (m_dirLister) + m_dirLister->updateDirectory( _url ); +} + + #include "kdiconview.moc" diff --git a/kdesktop/kdiconview.h b/kdesktop/kdiconview.h index 715a0eb5e..5ef349322 100644 --- a/kdesktop/kdiconview.h +++ b/kdesktop/kdiconview.h @@ -73,6 +73,8 @@ public: TQStringList selectedURLs(); + void update( const TQString &url ); + /** * Save the icon positions */ @@ -103,6 +105,10 @@ public: void startDirLister(); + TQPoint findPlaceForIconCol( int column, int dx, int dy ); + TQPoint findPlaceForIconRow( int row, int dx, int dy ); + TQPoint findPlaceForIcon( int column, int row ); + protected slots: // slots connected to the icon view @@ -112,8 +118,9 @@ protected slots: void slotMouseButtonClickedKDesktop(int _button, TQIconViewItem* _item, const TQPoint& _global); void slotContextMenuRequested(TQIconViewItem* _item, const TQPoint& _global); void slotEnableAction( const char * name, bool enabled ); +public slots: void slotAboutToCreate(const TQPoint &pos, const TQValueList<KIO::CopyInfo> &files); - +protected slots: void slotItemRenamed(TQIconViewItem*, const TQString &name); // slots connected to the directory lister diff --git a/kdesktop/lock/lockprocess.cc b/kdesktop/lock/lockprocess.cc index d589232a1..cdd5581e7 100644 --- a/kdesktop/lock/lockprocess.cc +++ b/kdesktop/lock/lockprocess.cc @@ -39,6 +39,8 @@ #include <kstdguiitem.h> #include <kpixmapeffect.h> #include <kpixmap.h> +#include <kwin.h> +#include <kwinmodule.h> #include <tqframe.h> #include <tqlabel.h> @@ -119,6 +121,8 @@ static void segv_handler(int) sleep(1); } +extern Atom qt_wm_state; + //=========================================================================== // // Screen saver handling process. Handles screensaver window, @@ -135,6 +139,8 @@ LockProcess::LockProcess(bool child, bool useBlankOnly) mRestoreXF86Lock(false), mForbidden(false), mAutoLogout(false), + mVkbdProcess(NULL), + mKWinModule(NULL), mPipeOpen(false), mPipeOpen_out(false), mInfoMessageDisplayed(false), @@ -1120,9 +1126,11 @@ bool LockProcess::checkPass() if (mAutoLogout) killTimer(mAutoLogoutTimerId); + showVkbd(); PasswordDlg passDlg( this, &greetPlugin); - int ret = execDialog( &passDlg ); + hideVkbd(); + if (mForceReject == true) { ret = TQDialog::Rejected; } @@ -1251,9 +1259,13 @@ bool LockProcess::x11Event(XEvent *event) switch (event->type) { - case KeyPress: case ButtonPress: case MotionNotify: + case ButtonRelease: + if( forwardVkbdEvent( event )) + return true; // filter out + // fall through + case KeyPress: if (mBusy || !mDialogs.isEmpty()) break; mBusy = true; @@ -1290,11 +1302,30 @@ bool LockProcess::x11Event(XEvent *event) case ConfigureNotify: // from SubstructureNotifyMask on the root window if(event->xconfigure.event == qt_xrootwin()) stayOnTop(); + for( TQValueList< VkbdWindow >::Iterator it = mVkbdWindows.begin(); + it != mVkbdWindows.end(); + ++it ) { + if( (*it).id == event->xconfigure.window ) { + (*it).rect = TQRect( event->xconfigure.x, event->xconfigure.y, + event->xconfigure.width, event->xconfigure.height ); + break; + } + } break; case MapNotify: // from SubstructureNotifyMask on the root window + windowAdded( event->xmap.window, false ); if( event->xmap.event == qt_xrootwin()) stayOnTop(); break; + case DestroyNotify: + for( TQValueList< VkbdWindow >::Iterator it = mVkbdWindows.begin(); + it != mVkbdWindows.end(); + ++it ) + if( (*it).id == event->xdestroywindow.window ) { + mVkbdWindows.remove( it ); + break; + } + break; } // We have grab with the grab window being the root window. @@ -1319,17 +1350,24 @@ bool LockProcess::x11Event(XEvent *event) void LockProcess::stayOnTop() { - if(!mDialogs.isEmpty()) + if(!mDialogs.isEmpty() || !mVkbdWindows.isEmpty()) { // this restacking is written in a way so that // if the stacking positions actually don't change, // all restacking operations will be no-op, // and no ConfigureNotify will be generated, // thus avoiding possible infinite loops - XRaiseWindow( qt_xdisplay(), mDialogs.first()->winId()); // raise topmost + if( !mVkbdWindows.isEmpty()) + XRaiseWindow( qt_xdisplay(), mVkbdWindows.first().id ); + else + XRaiseWindow( qt_xdisplay(), mDialogs.first()->winId()); // raise topmost // and stack others below it - Window* stack = new Window[ mDialogs.count() + 1 ]; + Window* stack = new Window[ mDialogs.count() + mVkbdWindows.count() + 1 ]; int count = 0; + for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); + it != mVkbdWindows.end(); + ++it ) + stack[ count++ ] = (*it).id; for( TQValueList< TQWidget* >::ConstIterator it = mDialogs.begin(); it != mDialogs.end(); ++it ) @@ -1428,4 +1466,200 @@ void LockProcess::msgBox( TQMessageBox::Icon type, const TQString &txt ) execDialog( &box ); } +static int run_vkbd = -1; +void LockProcess::showVkbd() +{ + if( run_vkbd == - 1 ) { + int status = system( "hal-find-by-property --key system.formfactor.subtype --string tabletpc" ); +// status = 0; // enable for testing + run_vkbd = ( WIFEXITED( status ) && WEXITSTATUS( status ) == 0 + && !KStandardDirs::findExe( "xvkbd" ).isEmpty()) ? 1 : 0; + } + if( run_vkbd ) { + mVkbdWindows.clear(); + mVkbdLastEventWindow = None; + mKWinModule = new KWinModule( NULL, KWinModule::INFO_WINDOWS ); + connect( mKWinModule, TQT_SIGNAL( windowAdded( WId )), TQT_SLOT( windowAdded( WId ))); + mVkbdProcess = new KProcess; + *mVkbdProcess << "xvkbd" << "-compact" << "-geometry" << "-0-0" << "-xdm"; + mVkbdProcess->start(); + } +} + +void LockProcess::hideVkbd() +{ + if( mVkbdProcess != NULL ) { + mVkbdProcess->kill(); + delete mVkbdProcess; + mVkbdProcess = NULL; + delete mKWinModule; + mKWinModule = NULL; + mVkbdWindows.clear(); + } +} + +void LockProcess::windowAdded( WId w ) +{ + windowAdded( w, true ); +} + +void LockProcess::windowAdded( WId w, bool managed ) +{ + KWin::WindowInfo info = KWin::windowInfo( w, 0, NET::WM2WindowClass ); + if( info.windowClassClass().lower() != "xvkbd" ) + return; + // Unmanaged windows (i.e. popups) don't currently work anyway, since they + // don't have WM_CLASS set anyway. I could perhaps try tricks with X id + // ranges if really needed. + if( managed ) { + // withdraw the window, wait for it to be withdrawn, reparent it directly + // to root at the right position + XWithdrawWindow( qt_xdisplay(), w, qt_xscreen()); + for(;;) { + Atom type; + int format; + unsigned long length, after; + unsigned char *data; + int r = XGetWindowProperty( qt_xdisplay(), w, qt_wm_state, 0, 2, + false, AnyPropertyType, &type, &format, + &length, &after, &data ); + bool withdrawn = true; + if ( r == Success && data && format == 32 ) { + Q_UINT32 *wstate = (Q_UINT32*)data; + withdrawn = (*wstate == WithdrawnState ); + XFree( (char *)data ); + } + if( withdrawn ) + break; + } + } + XSelectInput( qt_xdisplay(), w, StructureNotifyMask ); + XWindowAttributes attr_geom; + if( !XGetWindowAttributes( qt_xdisplay(), w, &attr_geom )) + return; + int x = XDisplayWidth( qt_xdisplay(), qt_xscreen()) - attr_geom.width; + int y = XDisplayHeight( qt_xdisplay(), qt_xscreen()) - attr_geom.height; + if( managed ) { + XSetWindowAttributes attr; + attr.override_redirect = True; + XChangeWindowAttributes( qt_xdisplay(), w, CWOverrideRedirect, &attr ); + XReparentWindow( qt_xdisplay(), w, qt_xrootwin(), x, y ); + XMapWindow( qt_xdisplay(), w ); + } + VkbdWindow data; + data.id = w; + data.rect = TQRect( x, y, attr_geom.width, attr_geom.height ); + mVkbdWindows.prepend( data ); +} + +bool LockProcess::forwardVkbdEvent( XEvent* event ) +{ + if( mVkbdProcess == NULL ) + return false; + TQPoint pos; + Time time; + switch( event->type ) + { + case ButtonPress: + case ButtonRelease: + pos = TQPoint( event->xbutton.x, event->xbutton.y ); + time = event->xbutton.time; + break; + case MotionNotify: + pos = TQPoint( event->xmotion.x, event->xmotion.y ); + time = event->xmotion.time; + break; + default: + return false; + } + // vkbd windows are kept topmost, so just find the first one in the position + for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); + it != mVkbdWindows.end(); + ++it ) { + if( (*it).rect.contains( pos )) { + // Find the subwindow where the event should actually go. + // Not exactly cheap in the number of X roundtrips but oh well. + Window window = (*it).id; + Window root, child; + int root_x, root_y, x, y; + unsigned int mask; + for(;;) { + if( !XQueryPointer( qt_xdisplay(), window, &root, &child, &root_x, &root_y, &x, &y, &mask )) + return false; + if( child == None ) + break; + window = child; + } + switch( event->type ) + { + case ButtonPress: + case ButtonRelease: + event->xbutton.x = x; + event->xbutton.y = y; + event->xbutton.subwindow = None; + break; + case MotionNotify: + event->xmotion.x = x; + event->xmotion.y = y; + event->xmotion.subwindow = None; + break; + } + event->xany.window = window; + sendVkbdFocusInOut( window, time ); + XSendEvent( qt_xdisplay(), window, False, 0, event ); + return true; + } + } + sendVkbdFocusInOut( None, time ); + return false; +} + +// Fake EnterNotify/LeaveNotify events as the mouse moves. They're not sent by X +// because of the grab and having them makes xvkbd highlight the buttons (but +// not needed otherwise it seems). +void LockProcess::sendVkbdFocusInOut( WId window, Time t ) +{ + if( mVkbdLastEventWindow == window ) + return; + if( mVkbdLastEventWindow != None ) { + XEvent e; + e.xcrossing.type = LeaveNotify; + e.xcrossing.display = qt_xdisplay(); + e.xcrossing.window = mVkbdLastEventWindow; + e.xcrossing.root = qt_xrootwin(); + e.xcrossing.subwindow = None; + e.xcrossing.time = t; + e.xcrossing.x = 0; + e.xcrossing.y = 0; + e.xcrossing.x_root = -1; + e.xcrossing.y_root = -1; + e.xcrossing.mode = NotifyNormal; + e.xcrossing.detail = NotifyAncestor; + e.xcrossing.same_screen = True; + e.xcrossing.focus = False; + e.xcrossing.state = 0; + XSendEvent( qt_xdisplay(), mVkbdLastEventWindow, False, 0, &e ); + } + mVkbdLastEventWindow = window; + if( mVkbdLastEventWindow != None ) { + XEvent e; + e.xcrossing.type = EnterNotify; + e.xcrossing.display = qt_xdisplay(); + e.xcrossing.window = mVkbdLastEventWindow; + e.xcrossing.root = qt_xrootwin(); + e.xcrossing.subwindow = None; + e.xcrossing.time = t; + e.xcrossing.x = 0; + e.xcrossing.y = 0; + e.xcrossing.x_root = 0; + e.xcrossing.y_root = 0; + e.xcrossing.mode = NotifyNormal; + e.xcrossing.detail = NotifyAncestor; + e.xcrossing.same_screen = True; + e.xcrossing.focus = False; + e.xcrossing.state = 0; + XSendEvent( qt_xdisplay(), mVkbdLastEventWindow, False, 0, &e ); + } +} + #include "lockprocess.moc" diff --git a/kdesktop/lock/lockprocess.h b/kdesktop/lock/lockprocess.h index cdbeb0da1..76ffb6013 100644 --- a/kdesktop/lock/lockprocess.h +++ b/kdesktop/lock/lockprocess.h @@ -23,6 +23,7 @@ #include <X11/Xlib.h> class KLibrary; +class KWinModule; struct GreeterPluginHandle { KLibrary *library; @@ -79,6 +80,7 @@ private slots: void suspend(); void checkDPMSActive(); void slotDeadTimePassed(); + void windowAdded( WId ); private: void configure(); @@ -103,6 +105,11 @@ private: void stayOnTop(); void lockXF86(); void unlockXF86(); + void showVkbd(); + void hideVkbd(); + bool forwardVkbdEvent( XEvent* event ); + void sendVkbdFocusInOut( WId window, Time t ); + void windowAdded( WId window, bool managed ); void resume( bool force ); static TQVariant getConf(void *ctx, const char *key, const TQVariant &dflt); @@ -135,18 +142,29 @@ private: int mAutoLogoutTimerId; int mAutoLogoutTimeout; bool mAutoLogout; - bool mInfoMessageDisplayed; - TQDialog *currentDialog; - bool mDialogControlLock; - bool mForceReject; + + TQTimer *resizeTimer; + unsigned int mkeyCode; + + KProcess* mVkbdProcess; + KWinModule* mKWinModule; + struct VkbdWindow + { + WId id; + QRect rect; + }; + QValueList< VkbdWindow > mVkbdWindows; + WId mVkbdLastEventWindow; bool mPipeOpen; int mPipe_fd; bool mPipeOpen_out; int mPipe_fd_out; - TQTimer *resizeTimer; - unsigned int mkeyCode; + bool mInfoMessageDisplayed; + TQDialog *currentDialog; + bool mDialogControlLock; + bool mForceReject; }; #endif diff --git a/kdesktop/minicli.cpp b/kdesktop/minicli.cpp index caef6197a..027aa0bfc 100644 --- a/kdesktop/minicli.cpp +++ b/kdesktop/minicli.cpp @@ -145,6 +145,9 @@ Minicli::Minicli( TQWidget *parent, const char *name) connect( m_dlg->cbCommand, TQT_SIGNAL( returnPressed() ), m_dlg->pbRun, TQT_SLOT( animateClick() ) ); + m_dlg->cbCommand->setHistoryEditorEnabled( true ); + connect( m_dlg->cbCommand, TQT_SIGNAL(removed( const TQString&) ), TQT_SLOT(saveConfig()) ); + // Advanced group box... connect(m_dlg->cbPriority, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotChangeScheduler(bool))); connect(m_dlg->slPriority, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotPriority(int))); @@ -295,7 +298,9 @@ void Minicli::accept() } bool logout = (cmd == "logout"); - if( !logout && runCommand() == 1 ) + bool lock = (cmd == "lock"); + + if( !logout && !lock && runCommand() == 1 ) return; m_dlg->cbCommand->addToHistory( m_dlg->cbCommand->currentText().stripWhiteSpace() ); @@ -308,6 +313,14 @@ void Minicli::accept() kapp->propagateSessionManager(); kapp->requestShutDown(); } + if ( lock ) + { + TQCString appname( "kdesktop" ); + int kicker_screen_number = qt_xscreen(); + if ( kicker_screen_number ) + appname.sprintf("kdesktop-screen-%d", kicker_screen_number); + kapp->dcopClient()->send(appname, "KScreensaverIface", "lock()", ""); + } } void Minicli::reject() diff --git a/kdesktop/minicli.h b/kdesktop/minicli.h index ddbe868c0..4ae49cf7c 100644 --- a/kdesktop/minicli.h +++ b/kdesktop/minicli.h @@ -54,12 +54,14 @@ public: void setCommand(const TQString& command); void reset(); - void saveConfig(); void clearHistory(); virtual void show(); virtual TQSize sizeHint() const; +public slots: + void saveConfig(); + protected slots: virtual void accept(); virtual void reject(); diff --git a/kdesu/kdesu/kdesu.cpp b/kdesu/kdesu/kdesu.cpp index af2986b06..67ea55fe9 100644 --- a/kdesu/kdesu/kdesu.cpp +++ b/kdesu/kdesu/kdesu.cpp @@ -382,6 +382,7 @@ static int startApp() change_uid = false; password = dlg.password(); keep = dlg.keep(); + KConfigGroup(config,"Passwords").writeEntry("Keep", keep); data.setSilent( KStartupInfoData::No ); KStartupInfo::sendChange( id, data ); } diff --git a/kdesu/kdesud/kdesud.cpp b/kdesu/kdesud/kdesud.cpp index 3e9462698..49006a401 100644 --- a/kdesu/kdesud/kdesud.cpp +++ b/kdesu/kdesud/kdesud.cpp @@ -45,6 +45,7 @@ #include <pwd.h> #include <errno.h> +#include <sys/prctl.h> #include <sys/time.h> #include <sys/stat.h> #include <sys/types.h> @@ -248,6 +249,8 @@ int create_socket() int main(int argc, char *argv[]) { + prctl(PR_SET_DUMPABLE, 0); + KAboutData aboutData("kdesud", I18N_NOOP("KDE su daemon"), Version, I18N_NOOP("Daemon used by kdesu"), KAboutData::License_Artistic, diff --git a/kdm/backend/client.c b/kdm/backend/client.c index b2e7ebbc7..0807b2ce7 100644 --- a/kdm/backend/client.c +++ b/kdm/backend/client.c @@ -87,6 +87,18 @@ extern int loginsuccess( const char *User, const char *Host, const char *Tty, ch #include "consolekit.h" #endif +#define AU_FAILED 0 +#define AU_SUCCESS 1 +#ifdef HAVE_LIBAUDIT +#include <libaudit.h> +#else +#define log_to_audit_system(l,h,d,s) do { ; } while (0) +#endif + +#ifdef WITH_CONSOLE_KIT +#include "consolekit.h" +#endif + /* * Session data, mostly what struct verify_info was for */ @@ -291,6 +303,56 @@ fail_delay( int retval ATTR_UNUSED, unsigned usec_delay ATTR_UNUSED, {} # endif + /** + * log_to_audit_system: + * @login: Name of user + * @hostname: Name of host machine + * @tty: Name of display + * @success: 1 for success, 0 for failure + * + * Logs the success or failure of the login attempt with the linux kernel + * audit system. The intent is to capture failed events where the user + * fails authentication or otherwise is not permitted to login. There are + * many other places where pam could potentially fail and cause login to + * fail, but these are system failures rather than the signs of an account + * being hacked. + * + * Returns nothing. + */ + +#ifdef HAVE_LIBAUDIT +static void +log_to_audit_system (const char *loginname, + const char *hostname, + const char *tty, + int success) +{ + struct passwd *pw; + char buf[64]; + int audit_fd; + + audit_fd = audit_open(); + if (loginname) + pw = getpwnam(loginname); + else { + loginname = "unknown"; + pw = NULL; + } + Debug("log_to_audit %p %s\n", pw, loginname); + + if (pw) { + snprintf(buf, sizeof(buf), "uid=%d", pw->pw_uid); + audit_log_user_message(audit_fd, AUDIT_USER_LOGIN, + buf, hostname, NULL, tty, (int)success); + } else { + snprintf(buf, sizeof(buf), "acct=%s", loginname); + audit_log_user_message(audit_fd, AUDIT_USER_LOGIN, + buf, hostname, NULL, tty, (int)success); + } + close(audit_fd); +} +#endif + static int doPAMAuth( const char *psrv, struct pam_data *pdata ) { @@ -349,6 +411,8 @@ doPAMAuth( const char *psrv, struct pam_data *pdata ) GSendStr( curuser ); } if (pretc != PAM_SUCCESS) { + /* Log the failed login attempt */ + log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); switch (pretc) { case PAM_USER_UNKNOWN: case PAM_AUTH_ERR: @@ -484,6 +548,9 @@ Verify( GConvFunc gconv, int rootok ) } else psrv = PAMService; pdata.usecur = TRUE; + } else if (!strcmp( curtype, "pam" )) { + psrv = PAMService; + pdata.usecur = FALSE; } else { sprintf( psrvb, "%.31s-%.31s", PAMService, curtype ); psrv = psrvb; @@ -553,7 +620,7 @@ Verify( GConvFunc gconv, int rootok ) free( msg ); V_RET_FAIL( 0 ); } - } else if (!strcmp( curtype, "generic" )) { + } else if (!strcmp( curtype, "generic" ) || !strcmp(curtype, "pam")) { if (!gconv( GCONV_USER, 0 )) return 0; for (curret = 0;;) { @@ -699,6 +766,8 @@ Verify( GConvFunc gconv, int rootok ) if (!p->pw_uid) { if (!rootok && !td->allowRootLogin) V_RET_FAIL( "Root logins are not allowed" ); + /* Log the failed login attempt */ + log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); return 1; /* don't deny root to log in */ } @@ -735,6 +804,8 @@ Verify( GConvFunc gconv, int rootok ) } if (pretc == PAM_SUCCESS) break; + /* Log the failed login attempt */ + log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); /* effectively there is only PAM_AUTHTOK_ERR */ GSendInt( V_FAIL ); } @@ -824,6 +895,8 @@ Verify( GConvFunc gconv, int rootok ) GSendInt( V_MSG_ERR ); GSendStr( "Your account has expired;" " please contact your system administrator" ); + /* Log the failed login attempt */ + log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); GSendInt( V_FAIL ); LC_RET0; } else if (tim > (expir - warntime) && !quietlog) { @@ -858,6 +931,8 @@ Verify( GConvFunc gconv, int rootok ) GSendInt( V_MSG_ERR ); GSendStr( "Your account has expired;" " please contact your system administrator" ); + /* Log the failed login attempt */ + log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); GSendInt( V_FAIL ); LC_RET0; } @@ -917,6 +992,8 @@ Verify( GConvFunc gconv, int rootok ) close( fd ); } GSendStr( "Logins are not allowed at the moment.\nTry again later" ); + /* Log the failed login attempt */ + log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); GSendInt( V_FAIL ); LC_RET0; } @@ -927,6 +1004,8 @@ Verify( GConvFunc gconv, int rootok ) PrepErrorGreet(); GSendInt( V_MSG_ERR ); GSendStr( "You are not allowed to login at the moment" ); + /* Log the failed login attempt */ + log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); GSendInt( V_FAIL ); LC_RET0; } @@ -938,6 +1017,8 @@ Verify( GConvFunc gconv, int rootok ) Debug( "shell not in /etc/shells\n" ); endusershell(); V_RET_FAIL( "Your login shell is not listed in /etc/shells" ); + /* Log the failed login attempt */ + log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); } if (!strcmp( s, p->pw_shell )) { endusershell(); @@ -1223,6 +1304,8 @@ StartClient() env = setEnv( env, "PATH", curuid ? td->userPath : td->systemPath ); env = setEnv( env, "SHELL", p->pw_shell ); env = setEnv( env, "HOME", p->pw_dir ); + if (cursource == PWSRC_AUTOLOGIN) + env = setEnv (env, "KDM_AUTOLOGIN", curuser); #if !defined(USE_PAM) && !defined(_AIX) && defined(KERBEROS) if (krbtkfile[0] != '\0') env = setEnv( env, "KRBTKFILE", krbtkfile ); @@ -1232,6 +1315,11 @@ StartClient() env = setEnv ( env, "XDG_SESSION_COOKIE", ck_session_cookie ); } #endif +#ifdef WITH_CONSOLE_KIT + if (ck_session_cookie != NULL) { + env = setEnv ( env, "XDG_SESSION_COOKIE", ck_session_cookie ); + } +#endif userEnviron = inheritEnv( env, envvars ); env = systemEnv( p->pw_name ); systemEnviron = setEnv( env, "HOME", p->pw_dir ); @@ -1360,6 +1448,9 @@ StartClient() # define D_LOGIN_SETGROUP 0 #endif /* USE_PAM */ + /* Login succeeded */ + log_to_audit_system (curuser, td->remoteHost, td->name, AU_SUCCESS); + removeAuth = 1; chownCtrl( &td->ctrl, curuid ); endpwent(); diff --git a/kdm/config.def b/kdm/config.def index ab1adac84..7bc39b36d 100644 --- a/kdm/config.def +++ b/kdm/config.def @@ -1985,6 +1985,17 @@ Description: Specify the widget style for the greeter. Empty means to use the built-in default which currently is <literal>Plastik</literal>. +Key: UseAdminSession +Type: bool +Default: false +User: greeter +Instance: #*/! +Comment: + Admin session +Description: + If given there will be a special button that requires root password + and starts the given session + Key: ColorScheme Type: string Default: "" diff --git a/kdm/configure.in.in b/kdm/configure.in.in index 4b6972178..da741e7f9 100644 --- a/kdm/configure.in.in +++ b/kdm/configure.in.in @@ -287,4 +287,75 @@ fi AC_SUBST(DBUS_INCS) AC_SUBST(DBUS_LIBS) +########### Check for DBus + + AC_MSG_CHECKING(for DBus) + + dbus_inc=NOTFOUND + dbus_lib=NOTFOUND + dbus=NOTFOUND + + search_incs="$kde_includes $kde_extra_includes /usr/include /usr/include/dbus-1.0 /usr/local/include /usr/local/include/dbus-1.0" + AC_FIND_FILE(dbus/dbus.h, $search_incs, dbus_incdir) + + search_incs_arch_deps="$kde_includes $kde_extra_includes /usr/lib$kdelibsuff/dbus-1.0/include /usr/local/lib$kdelibsuff/dbus-1.0/include" + AC_FIND_FILE(dbus/dbus-arch-deps.h, $search_incs_arch_deps, dbus_incdir_arch_deps) + + if test -r $dbus_incdir/dbus/dbus.h && test -r $dbus_incdir_arch_deps/dbus/dbus-arch-deps.h ; then + DBUS_INCS="-I$dbus_incdir -I$dbus_incdir_arch_deps" + dbus_inc=FOUND + fi + + search_libs="$kde_libraries $kde_extra_libs /usr/lib$kdelibsuff /usr/local/lib$kdelibsuff" + AC_FIND_FILE(libdbus-1.so, $search_libs, dbus_libdir) + + if test -r $dbus_libdir/libdbus-1.so ; then + DBUS_LIBS="-L$dbus_libdir -ldbus-1" + dbus_lib=FOUND + fi + + if test $dbus_inc != FOUND || test $dbus_lib != FOUND ; then + KDE_PKG_CHECK_MODULES( DBUS, "dbus-1", [ DBUS_INCS=$DBUS_CFLAGS; dbus_inc=FOUND; dbus_lib=FOUND; ] , AC_MSG_RESULT( Nothing found on PKG_CONFIG_PATH ) ) + fi + + dbus_bus_var=`pkg-config --variable=system_bus_default_address dbus-1 2>/dev/null` + if test -z "$dbus_bus_var"; then + dbus_bus_var="unix:path=/var/run/dbus/system_bus_socket" + fi + AC_DEFINE_UNQUOTED(DBUS_SYSTEM_BUS, "$dbus_bus_var", [Define the unix domain path for dbus system bus]) + + if test $dbus_inc = FOUND && test $dbus_lib = FOUND ; then + AC_MSG_RESULT(headers $DBUS_INCS libraries $DBUS_LIBS) + dbus=FOUND + else + AC_MSG_RESULT(searched but not found) + fi + + AC_SUBST(DBUS_INCS) + AC_SUBST(DBUS_LIBS) + dnl AC_OUTPUT(kdm/kfrontend/sessions/kde.desktop) + + +AC_ARG_WITH(libaudit, + [ --with-libaudit=[auto/yes/no] Add Linux audit support [default=auto]],, + with_libaudit=auto) + +# Check for Linux auditing API +# +# libaudit detection +if test x$with_libaudit = xno ; then + have_libaudit=no; +else + # See if we have audit daemon library + AC_CHECK_LIB(audit, audit_log_user_message, + have_libaudit=yes, have_libaudit=no) +fi + +AM_CONDITIONAL(HAVE_LIBAUDIT, test x$have_libaudit = xyes) + +if test x$have_libaudit = xyes ; then + EXTRA_DAEMON_LIBS="$EXTRA_DAEMON_LIBS -laudit" + AC_DEFINE(HAVE_LIBAUDIT,1,[linux audit support]) +fi + diff --git a/kdm/kfrontend/Makefile.am b/kdm/kfrontend/Makefile.am index 5c5dfd61a..6d4fed27b 100644 --- a/kdm/kfrontend/Makefile.am +++ b/kdm/kfrontend/Makefile.am @@ -21,6 +21,7 @@ kdm_greet_SOURCES = \ kchooser.cpp \ kgverify.cpp \ kdmshutdown.cpp \ + kdmadmindialog.cpp \ kgreeter.cpp \ kgapp.cpp kdm_greet_LDFLAGS = $(all_libraries) $(KDE_RPATH) diff --git a/kdm/kfrontend/kdm_greet.c b/kdm/kfrontend/kdm_greet.c index 53d164f45..b03d96e15 100644 --- a/kdm/kfrontend/kdm_greet.c +++ b/kdm/kfrontend/kdm_greet.c @@ -44,8 +44,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # include <sched.h> #endif -#if defined(HAVE_XTEST) || defined(HAVE_XKB) # include <X11/Xlib.h> +#if defined(HAVE_XTEST) || defined(HAVE_XKB) # include <X11/keysym.h> #endif diff --git a/kdm/kfrontend/kdmadmindialog.cpp b/kdm/kfrontend/kdmadmindialog.cpp new file mode 100644 index 000000000..637d6dd90 --- /dev/null +++ b/kdm/kfrontend/kdmadmindialog.cpp @@ -0,0 +1,176 @@ + /* + + Admin dialog + + Copyright (C) 1997, 1998, 2000 Steffen Hansen <[email protected]> + Copyright (C) 2000-2003 Oswald Buddenhagen <[email protected]> + + + 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 "kdmadmindialog.h" +#include "kdmconfig.h" +#include "kgdialog.h" +#include "kdm_greet.h" +#include <stdlib.h> + +#include <kapplication.h> +#include <kseparator.h> +#include <klocale.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> + +#include <tqcombobox.h> +#include <tqvbuttongroup.h> +#include <tqstyle.h> +#include <tqlayout.h> +#include <tqaccel.h> +#include <tqpopupmenu.h> + +int KDMAdmin::curPlugin = -1; +PluginList KDMAdmin::pluginList; + +KDMAdmin::KDMAdmin( const TQString &user, TQWidget *_parent ) + : inherited( _parent ) + , verify( 0 ), curUser(user) +{ + TQSizePolicy fp( TQSizePolicy::Fixed, TQSizePolicy::Fixed ); + + TQVBoxLayout *box = new TQVBoxLayout( this, 10 ); + + TQHBoxLayout *hlay = new TQHBoxLayout( box ); + + GSendInt( G_ReadDmrc ); + GSendStr( "root" ); + GRecvInt(); // ignore status code ... + + if (curPlugin < 0) { + curPlugin = 0; + pluginList = KGVerify::init( "classic" ); + } + verify = new KGStdVerify( this, this, + this, "root", + pluginList, KGreeterPlugin::Authenticate, + KGreeterPlugin::Shutdown ); + verify->selectPlugin( curPlugin ); + box->addLayout( verify->getLayout() ); + TQAccel *accel = new TQAccel( this ); + accel->insertItem( ALT+Key_A, 0 ); + connect( accel, TQT_SIGNAL(activated(int)), TQT_SLOT(slotActivatePlugMenu()) ); + + box->addWidget( new KSeparator( KSeparator::HLine, this ) ); + + okButton = new KPushButton( KStdGuiItem::ok(), this ); + okButton->setSizePolicy( fp ); + okButton->setDefault( true ); + cancelButton = new KPushButton( KStdGuiItem::cancel(), this ); + cancelButton->setSizePolicy( fp ); + + hlay = new TQHBoxLayout( box ); + hlay->addStretch( 1 ); + hlay->addWidget( okButton ); + hlay->addStretch( 1 ); + hlay->addWidget( cancelButton ); + hlay->addStretch( 1 ); + + connect( okButton, TQT_SIGNAL(clicked()), TQT_SLOT(accept()) ); + connect( cancelButton, TQT_SIGNAL(clicked()), TQT_SLOT(reject()) ); + + slotWhenChanged(); +} + +KDMAdmin::~KDMAdmin() +{ + hide(); + delete verify; +} + +void +KDMAdmin::slotActivatePlugMenu() +{ + TQPopupMenu *cmnu = verify->getPlugMenu(); + TQSize sh( cmnu->sizeHint() / 2 ); + cmnu->exec( geometry().center() - TQPoint( sh.width(), sh.height() ) ); +} + +void +KDMAdmin::accept() +{ + verify->accept(); +} + +void +KDMAdmin::slotWhenChanged() +{ + verify->abort(); + verify->setEnabled( 1 ); + verify->start(); +} + +void +KDMAdmin::bye_bye() +{ + GSendInt( G_GetDmrc ); + GSendStr( "Session" ); + char *sess = GRecvStr(); + if (sess && strcmp(sess, "admin")) { + GSendInt( G_PutDmrc ); + GSendStr( "OrigSession"); + GSendStr( sess); + free(sess); + } + + GSendInt( G_PutDmrc ); + GSendStr( "Session" ); + GSendStr( "admin" ); + inherited::accept(); +} + +void +KDMAdmin::verifyPluginChanged( int id ) +{ + curPlugin = id; + adjustSize(); +} + +void +KDMAdmin::verifyOk() +{ + bye_bye(); +} + +void +KDMAdmin::verifyFailed() +{ + okButton->setEnabled( false ); + cancelButton->setEnabled( false ); +} + +void +KDMAdmin::verifyRetry() +{ + okButton->setEnabled( true ); + cancelButton->setEnabled( true ); +} + +void +KDMAdmin::verifySetUser( const TQString & ) +{ +} + + +#include "kdmadmindialog.moc" diff --git a/kdm/kfrontend/kdmadmindialog.h b/kdm/kfrontend/kdmadmindialog.h new file mode 100644 index 000000000..91f1ed3a6 --- /dev/null +++ b/kdm/kfrontend/kdmadmindialog.h @@ -0,0 +1,70 @@ + /* + + Shutdown dialog + + Copyright (C) 1997, 1998 Steffen Hansen <[email protected]> + Copyright (C) 2000-2003 Oswald Buddenhagen <[email protected]> + + + 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 KDMADMIN_H +#define KDMADMIN_H + +#include "kgverify.h" + +#include <tqradiobutton.h> + +class LiloInfo; +class TQLabel; +class KPushButton; +class TQButtonGroup; +class TQComboBox; + +class KDMAdmin : public FDialog, public KGVerifyHandler { + Q_OBJECT + typedef FDialog inherited; + +public: + KDMAdmin( const TQString &user, TQWidget *_parent = 0 ); + ~KDMAdmin(); + +public slots: + void accept(); + void slotWhenChanged(); + void slotActivatePlugMenu(); + +private: + void bye_bye(); + + KPushButton *okButton, *cancelButton; + KGStdVerify *verify; + TQString curUser; + + static int curPlugin; + static PluginList pluginList; + +public: // from KGVerifyHandler + virtual void verifyPluginChanged( int id ); + virtual void verifyOk(); + virtual void verifyFailed(); + virtual void verifyRetry(); + virtual void verifySetUser( const TQString &user ); +}; + +#endif diff --git a/kdm/kfrontend/kdmconfig.cpp b/kdm/kfrontend/kdmconfig.cpp index 6f4c14031..15a63fa67 100644 --- a/kdm/kfrontend/kdmconfig.cpp +++ b/kdm/kfrontend/kdmconfig.cpp @@ -33,6 +33,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include <unistd.h> #include <sys/utsname.h> +struct timeval st = {0, 0}; + CONF_GREET_DEFS TQString _stsFile; diff --git a/kdm/kfrontend/kdmconfig.h b/kdm/kfrontend/kdmconfig.h index f5420bcc4..52e054af6 100644 --- a/kdm/kfrontend/kdmconfig.h +++ b/kdm/kfrontend/kdmconfig.h @@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include <tqstring.h> #include <tqstringlist.h> #include <tqfont.h> +#include <sys/time.h> extern TQString _stsFile; extern bool _isLocal; @@ -46,6 +47,19 @@ CONF_GREET_CPP_DECLS struct dpySpec; void decodeSess( dpySpec *sess, TQString &user, TQString &loc ); +extern struct timeval st; + +inline TQString timestamp() { + struct timeval nst; + gettimeofday(&nst, 0); + if (!st.tv_sec) + gettimeofday(&st, 0); + + TQString ret; + ret.sprintf("[%07ld]", (nst.tv_sec - st.tv_sec) * 1000 + (nst.tv_usec - st.tv_usec) / 1000); + return ret; +} + extern "C" #endif void init_config( void ); diff --git a/kdm/kfrontend/kfdialog.cpp b/kdm/kfrontend/kfdialog.cpp index 62a4acb22..78359e237 100644 --- a/kdm/kfrontend/kfdialog.cpp +++ b/kdm/kfrontend/kfdialog.cpp @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include <klocale.h> #include <kpushbutton.h> #include <kstdguiitem.h> +#include <kglobalsettings.h> #include <tqlabel.h> #include <tqlayout.h> @@ -137,6 +138,9 @@ KFMsgBox::KFMsgBox( TQWidget *parent, TQMessageBox::Icon type, const TQString &t TQLabel *label1 = new TQLabel( this ); label1->setPixmap( TQMessageBox::standardIcon( type ) ); TQLabel *label2 = new TQLabel( text, this ); + TQRect d = KGlobalSettings::desktopGeometry(this); + if ( label2->fontMetrics().size( 0, text).width() > d.width() * 3 / 5) + label2->setAlignment(Qt::WordBreak | Qt::AlignAuto ); KPushButton *button = new KPushButton( KStdGuiItem::ok(), this ); button->setDefault( true ); button->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) ); diff --git a/kdm/kfrontend/kgapp.cpp b/kdm/kfrontend/kgapp.cpp index 70b510645..50e65e916 100644 --- a/kdm/kfrontend/kgapp.cpp +++ b/kdm/kfrontend/kgapp.cpp @@ -36,6 +36,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include <kcrash.h> #include <kstandarddirs.h> #include <ksimpleconfig.h> +#include <klocale.h> +#include <kdebug.h> #include <tqtimer.h> #include <tqstring.h> @@ -133,6 +135,7 @@ kg_main( const char *argv0 ) static char *argv[] = { (char *)"kdmgreet", 0 }; KCmdLineArgs::init( 1, argv, *argv, 0, 0, 0, true ); + kdDebug() << timestamp() << "start" << endl; kde_have_kipc = false; KApplication::disableAutoDcopRegistration(); KCrash::setSafer( true ); @@ -180,6 +183,7 @@ kg_main( const char *argv0 ) GSendInt( G_Ready ); + kdDebug() << timestamp() << " main1" << endl; setCursor( dpy, app.desktop()->winId(), XC_left_ptr ); for (;;) { @@ -220,6 +224,7 @@ kg_main( const char *argv0 ) if (_useTheme && !_theme.isEmpty()) { KThemedGreeter *tgrt; dialog = tgrt = new KThemedGreeter; + kdDebug() << timestamp() << " themed" << endl; if (!tgrt->isOK()) { delete tgrt; dialog = new KStdGreeter; diff --git a/kdm/kfrontend/kgdialog.cpp b/kdm/kfrontend/kgdialog.cpp index 1981eea83..f4ed918c6 100644 --- a/kdm/kfrontend/kgdialog.cpp +++ b/kdm/kfrontend/kgdialog.cpp @@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "kdm_greet.h" #include <klocale.h> +#include <kiconloader.h> #include <tqaccel.h> #include <tqlayout.h> @@ -84,7 +85,8 @@ KGDialog::completeMenu() inserten( i18n("Co&nsole Login"), ALT+Key_N, TQT_SLOT(slotConsole()) ); if (_allowShutdown != SHUT_NONE) { - inserten( i18n("&Shutdown..."), ALT+Key_S, TQT_SLOT(slotShutdown( int )) ); + ensureMenu(); + optMenu->insertItem(SmallIconSet( "exit" ), i18n("&Shutdown..."), this, TQT_SLOT(slotShutdown(int)), ALT+Key_S ); TQAccel *accel = new TQAccel( this ); accel->insertItem( ALT+CTRL+Key_Delete ); connect( accel, TQT_SIGNAL(activated( int )), TQT_SLOT(slotShutdown( int )) ); diff --git a/kdm/kfrontend/kgreeter.cpp b/kdm/kfrontend/kgreeter.cpp index ebd303525..74fc6b090 100644 --- a/kdm/kfrontend/kgreeter.cpp +++ b/kdm/kfrontend/kgreeter.cpp @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "kdmconfig.h" #include "kdmclock.h" #include "kdm_greet.h" +#include "kdmadmindialog.h" #include "themer/kdmthemer.h" #include "themer/kdmitem.h" #include "themer/kdmlabel.h" @@ -38,6 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include <klistview.h> #include <ksimpleconfig.h> #include <kstringhandler.h> +#include <kdebug.h> #undef Unsorted // x headers suck - make tqdir.h work with --enable-final #include <tqdir.h> @@ -46,6 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include <tqmemarray.h> #include <tqimage.h> #include <tqmovie.h> +#include <tqpainter.h> #include <tqpopupmenu.h> #include <tqtimer.h> #include <tqheader.h> @@ -57,6 +60,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include <tqaccel.h> #include <tqstring.h> #include <tqeventloop.h> +#include <tqbitmap.h> #include <pwd.h> #include <grp.h> @@ -64,27 +68,46 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include <unistd.h> #include <fcntl.h> #include <sys/types.h> +#include <utmp.h> +#include <utmpx.h> #include <X11/Xlib.h> class UserListView : public KListView { public: - UserListView( TQWidget *parent = 0, const char *name = 0 ) + UserListView( bool _them, TQWidget *parent = 0, const char *name = 0 ) : KListView( parent, name ) - , cachedSizeHint( -1, 0 ) + , themed(_them), cachedSizeHint( -1, 0 ) { setSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Ignored ); header()->hide(); addColumn( TQString::null ); setColumnAlignment( 0, AlignVCenter ); setResizeMode( TQListView::LastColumn ); + if (themed) { + setBackgroundMode( Qt::NoBackground ); + viewport()->setBackgroundMode( Qt::NoBackground ); + setFrameStyle( TQFrame::NoFrame ); + } } + bool themed; mutable TQSize cachedSizeHint; - protected: + int sumHeight() const + { + int sum = 0; + for (TQListViewItem *itm = firstChild(); itm; itm = itm->nextSibling()) { + sum += itm->height(); + } + return sum; + } +public: virtual TQSize sizeHint() const { + if (themed) + return KListView::sizeHint(); + if (!cachedSizeHint.isValid()) { constPolish(); uint maxw = 0; @@ -99,9 +122,24 @@ class UserListView : public KListView { } return cachedSizeHint; } + virtual void paintEmptyArea ( TQPainter * p, const TQRect & rect ) + { + if (!themed) + return KListView::paintEmptyArea(p, rect ); + + const TQPixmap *pm = paletteBackgroundPixmap(); + if (!pm || pm->isNull()) + return; + + kdDebug() << "paintEmpty " << rect << endl; + TQRect devRect = p->xForm( rect ); + kdDebug() << "paintEmpty2 " << devRect << endl; + p->drawPixmap(0, 0, *pm, devRect.left(), devRect.top() ); + } + + TQPixmap background; }; - int KGreeter::curPlugin = -1; PluginList KGreeter::pluginList; @@ -116,12 +154,14 @@ KGreeter::KGreeter( bool framed ) , curSel( -1 ) , prevValid( true ) , needLoad( false ) + , themed( framed ) { stsFile = new KSimpleConfig( _stsFile ); stsFile->setGroup( "PrevUser" ); if (_userList) { - userView = new UserListView( this ); + readFacesList(); + userView = new UserListView( framed, this ); connect( userView, TQT_SIGNAL(clicked( TQListViewItem * )), TQT_SLOT(slotUserClicked( TQListViewItem * )) ); connect( userView, TQT_SIGNAL(doubleClicked( TQListViewItem * )), @@ -129,10 +169,8 @@ KGreeter::KGreeter( bool framed ) } if (_userCompletion) userList = new TQStringList; - if (userView || userList) - insertUsers(); - sessMenu = new TQPopupMenu( this ); + sessMenu = new TQPopupMenu( this ); connect( sessMenu, TQT_SIGNAL(activated( int )), TQT_SLOT(slotSessionSelected( int )) ); insertSessions(); @@ -151,6 +189,33 @@ KGreeter::~KGreeter() delete stsFile; } +void KGreeter::readFacesList() +{ + FILE *f = fopen( TQFile::encodeName( _faceDir + "/.randomlist" ), "rt" ); + if ( !f ) + return; + TQTextIStream is( f ); + while ( !is.eof() ) + { + TQString line = is.readLine().simplifyWhiteSpace(); + if ( line.isEmpty() ) + continue; + TQString icon; + int index = line.find( ' ' ); + if ( index > 0 ) { + icon = line.left( index ); + line = line.mid( index ); + } else { + icon = line; + line = TQString::null; + } + randomFaces.push_back( icon ); + TQStringList list = TQStringList::split( ' ', line ); + for ( TQStringList::ConstIterator it = list.begin(); it != list.end(); ++it ) + randomFacesMap[*it] = icon; + } +} + class UserListViewItem : public KListViewItem { public: UserListViewItem( UserListView *parent, const TQString &text, @@ -164,6 +229,14 @@ class UserListViewItem : public KListViewItem { parent->cachedSizeHint.setWidth( -1 ); } + virtual void paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int alignment) + { + if (((UserListView*)listView())->themed) + TQListViewItem::paintCell(p, cg, column, width, alignment); + else + KListViewItem::paintCell(p, cg, column, width, alignment); + } + TQString login; }; @@ -232,10 +305,23 @@ KGreeter::insertUser( const TQImage &default_pix, TQSize ns( 48, 48 ); if (p.size() != ns) p = p.convertDepth( 32 ).smoothScale( ns, TQImage::ScaleMin ); - goto gotit; + break; } while (--nd >= 0); - p = default_pix; - gotit: + + if ( p.isNull() && randomFaces.count() ) { + TQString randomFace = randomFacesMap[username]; + if ( randomFace.isNull() ) { + TQStringList::size_type index = 0; + for ( size_t i = 0; i < username.length(); ++i ) + index += ( 0x7f - username.at( i ).latin1() ) % 37; + randomFace = randomFaces[ index % randomFaces.count() ]; + } + p.load( _faceDir + "/../pics/users/" + randomFace + ".png" ); + } + + if ( p.isNull() ) + p = default_pix; + TQString realname = KStringHandler::from8Bit( ps->pw_gecos ); realname.truncate( realname.find( ',' ) ); if (realname.isEmpty() || realname == username) @@ -289,7 +375,7 @@ UserList::UserList( char **in ) } void -KGreeter::insertUsers() +KGreeter::insertUsers(int limit_users) { struct passwd *ps; @@ -309,6 +395,8 @@ KGreeter::insertUsers() if (_showUsers == SHOW_ALL) { UserList noUsers( _noUsers ); TQDict<int> dupes( 1000 ); + TQStringList toinsert; + int count = 0; for (setpwent(); (ps = getpwent()) != 0;) { if (*ps->pw_dir && *ps->pw_shell && (ps->pw_uid >= (unsigned)_lowUserId || @@ -320,10 +408,53 @@ KGreeter::insertUsers() TQString username( TQFile::decodeName( ps->pw_name ) ); if (!dupes.find( username )) { dupes.insert( username, (int *)-1 ); - insertUser( default_pix, username, ps ); + toinsert.append( username ); + + if ( limit_users >= 0 && ++count > limit_users ) + break; } } } + if ( limit_users >= 0 && ++count > limit_users ) { + utmpname( _PATH_WTMP ); + setutxent(); + toinsert = TQStringList(); + dupes.clear(); + + for ( count = 0; count < limit_users; ) { + struct utmpx * ent = getutxent(); + if ( !ent ) + break; + struct passwd *ps = getpwnam( ent->ut_user ); + if (ps && *ps->pw_dir && *ps->pw_shell && + (ps->pw_uid >= (unsigned)_lowUserId || + !ps->pw_uid && _showRoot) && + ps->pw_uid <= (unsigned)_highUserId && + !noUsers.hasUser( ps->pw_name ) && + !noUsers.hasGroup( ps->pw_gid )) + { + TQString username( TQFile::decodeName( ent->ut_user ) ); + if (!dupes.find( username )) { + dupes.insert( username, (int *)-1 ); + toinsert.append( username ); + count++; + } + } + + + } + endutxent(); + } + + for ( TQStringList::ConstIterator it = toinsert.begin(); + it != toinsert.end(); ++it ) + { + // pretty stupid to do another lookup round, but the number is limited + // and caching struct passwd is pretty ugly + struct passwd *ps = getpwnam( TQFile::encodeName( *it ) ); + if ( ps ) + insertUser( default_pix, *it, ps ); + } } else { UserList users( _users ); if (users.hasGroups()) { @@ -379,7 +510,7 @@ KGreeter::insertSessions() for (char **dit = _sessionsDirs; *dit; ++dit) { TQStringList ents = TQDir( *dit ).entryList(); for (TQStringList::ConstIterator it = ents.begin(); it != ents.end(); ++it) - if ((*it).endsWith( ".desktop" )) { + if ((*it).endsWith( ".desktop" ) && !(*it).endsWith("admin.desktop")) { KSimpleConfig dsk( TQString( *dit ).append( '/' ).append( *it ) ); dsk.setGroup( "Desktop Entry" ); putSession( (*it).left( (*it).length() - 8 ), @@ -517,6 +648,17 @@ KGreeter::slotLoadPrevWM() return; } } else { + if (!strcmp(sess, "admin")) { + // need to get the original + GSendInt( G_GetDmrc); + GSendStr( "OrigSession"); + sess = GRecvStr(); + if (!sess) { + free(sess); + sess = strdup("default"); + } + } + for (uint i = 0; i < sessionTypes.count() && !sessionTypes[i].hid; i++) if (sessionTypes[i].type == sess) { free( sess ); @@ -718,21 +860,24 @@ KStdGreeter::KStdGreeter() hbox2->addStretch( 1 ); if (sessMenu->count() > 1) { - inserten( i18n("Session &Type"), ALT+Key_T, sessMenu ); + inserten( i18n("Session &Type"), 0, sessMenu ); needSep = true; } if (plugMenu) { - inserten( i18n("&Authentication Method"), ALT+Key_A, plugMenu ); + inserten( i18n("&Authentication Method"), 0, plugMenu ); needSep = true; } #ifdef XDMCP - completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), ALT+Key_R ); + completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), 0 ); #else completeMenu(); #endif + if (userView || userList) + insertUsers(); + if (optMenu) menuButton->setPopup( optMenu ); else @@ -826,6 +971,9 @@ KThemedGreeter::KThemedGreeter() if (xauth_warning && (_authorized || !_authComplain)) xauth_warning->hide( true ); + if (userView || userList) + insertUsers( 7 ); // TODO: find out how many are a good value + // if (!_greetString.isEmpty()) { // } // clock = new KdmClock( this, "clock" ); @@ -851,12 +999,8 @@ KThemedGreeter::KThemedGreeter() if ((itm = themer->findNode( "session_button" ))) { if (sessMenu->count() <= 1) itm->hide( true ); - else { + else session_button = itm; - TQAccel *accel = new TQAccel( this ); - accel->insertItem( ALT+Key_T, 0 ); - connect( accel, TQT_SIGNAL(activated( int )), TQT_SLOT(slotSessMenu()) ); - } } else { if (sessMenu->count() > 1) { inserten( i18n("Session &Type"), ALT+Key_T, sessMenu ); @@ -864,6 +1008,12 @@ KThemedGreeter::KThemedGreeter() } } + admin_button = themer->findNode( "admin_button"); + if ( admin_button ) { + if ( !_useAdminSession ) + admin_button->hide( true ); + } + if (plugMenu) { inserten( i18n("&Authentication Method"), ALT+Key_A, plugMenu ); needSep = true; @@ -899,8 +1049,8 @@ KThemedGreeter::pluginSetup() inherited::pluginSetup(); if (userView && verify->entitiesLocal() && verify->entityPresettable() && userlist_rect) { + userView->setMaximumHeight( userView->sumHeight() ); userlist_rect->setWidget( userView ); - userView->show(); } else { if (userView) userView->hide(); @@ -916,12 +1066,17 @@ KThemedGreeter::verifyFailed() { // goButton->setEnabled( false ); inherited::verifyFailed(); + if (userView) + userView->setEnabled(false); } void KThemedGreeter::verifyRetry() { // goButton->setEnabled( true ); + if (userView) + userView->setEnabled(true); + } TQString KThemedGreeter::timedUser = TQString::null; @@ -966,6 +1121,8 @@ KThemedGreeter::slotThemeActivated( const TQString &id ) slotSessMenu(); else if (id == "system_button") slotActionMenu(); + else if (id == "admin_button") + slotAskAdminPassword(); } void @@ -992,4 +1149,15 @@ KThemedGreeter::keyPressEvent( TQKeyEvent *e ) accept(); } +void +KThemedGreeter::slotAskAdminPassword() +{ + KDMAdmin k(curUser, this); + if (k.exec()) { + GSendInt(G_Ready); + hide(); + done(ex_exit); + } +} + #include "kgreeter.moc" diff --git a/kdm/kfrontend/kgreeter.h b/kdm/kfrontend/kgreeter.h index 61673badf..fdbd56209 100644 --- a/kdm/kfrontend/kgreeter.h +++ b/kdm/kfrontend/kgreeter.h @@ -73,9 +73,10 @@ class KGreeter : public KGDialog, public KGVerifyHandler { void slotUserEntered(); protected: + void readFacesList(); void installUserList(); void insertUser( const TQImage &, const TQString &, struct passwd * ); - void insertUsers(); + void insertUsers( int limit = -1); void putSession( const TQString &, const TQString &, bool, const char * ); void insertSessions(); virtual void pluginSetup(); @@ -87,10 +88,13 @@ class KGreeter : public KGDialog, public KGVerifyHandler { TQStringList *userList; TQPopupMenu *sessMenu; TQValueVector<SessType> sessionTypes; + TQStringList randomFaces; + TQMap<TQString, TQString> randomFacesMap; int nNormals, nSpecials; int curPrev, curSel; bool prevValid; bool needLoad; + bool themed; static int curPlugin; static PluginList pluginList; @@ -142,6 +146,7 @@ class KThemedGreeter : public KGreeter { void slotThemeActivated( const TQString &id ); void slotSessMenu(); void slotActionMenu(); + void slotAskAdminPassword(); protected: virtual void updateStatus( bool fail, bool caps, int timedleft ); @@ -154,7 +159,7 @@ class KThemedGreeter : public KGreeter { KdmThemer *themer; KdmItem *caps_warning, *xauth_warning, *pam_error, *timed_label, *console_rect, *userlist_rect, - *session_button, *system_button; + *session_button, *system_button, *admin_button; public: // from KGVerifyHandler virtual void verifyFailed(); diff --git a/kdm/kfrontend/sessions/Makefile.am b/kdm/kfrontend/sessions/Makefile.am index 14577ac42..71655c9a4 100644 --- a/kdm/kfrontend/sessions/Makefile.am +++ b/kdm/kfrontend/sessions/Makefile.am @@ -1,6 +1,6 @@ sessionsdir = $(kde_datadir)/kdm/sessions sessions_DATA = \ - kde.desktop gnome.desktop \ + admin.desktop kde.desktop gnome.desktop \ 9wm.desktop \ aewm++.desktop \ aewm.desktop \ diff --git a/kdm/kfrontend/sessions/admin.desktop b/kdm/kfrontend/sessions/admin.desktop new file mode 100644 index 000000000..73e6ae3bf --- /dev/null +++ b/kdm/kfrontend/sessions/admin.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=XSession +Exec=YaSTadminSession +TryExec=YaSTadminSession +Name=admin +Comment=Yast Admin Session diff --git a/kdm/kfrontend/themer/kdmitem.cpp b/kdm/kfrontend/themer/kdmitem.cpp index 38af9d0aa..d47c0242d 100644 --- a/kdm/kfrontend/themer/kdmitem.cpp +++ b/kdm/kfrontend/themer/kdmitem.cpp @@ -23,10 +23,11 @@ * Generic Kdm Item */ -//#define DRAW_OUTLINE 1 // for debugging only +// #define DRAW_OUTLINE 1 // for debugging only #include "kdmitem.h" #include "kdmlayout.h" +#include "kdmconfig.h" #include <kglobal.h> #include <kdebug.h> @@ -35,9 +36,7 @@ #include <tqwidget.h> #include <tqlayout.h> #include <tqimage.h> -#ifdef DRAW_OUTLINE -# include <tqpainter.h> -#endif +#include <tqpainter.h> KdmItem::KdmItem( KdmItem *parent, const TQDomNode &node, const char *name ) : TQObject( parent, name ) @@ -48,6 +47,25 @@ KdmItem::KdmItem( KdmItem *parent, const TQDomNode &node, const char *name ) , myLayoutItem( 0 ) , buttonParent( 0 ) { + init(node, name); +} + + +KdmItem::KdmItem( TQWidget *parent, const TQDomNode &node, const char *name ) + : TQObject( parent, name ) + , boxManager( 0 ) + , fixedManager( 0 ) + , image( 0 ) + , myWidget( 0 ) + , myLayoutItem( 0 ) + , buttonParent( 0 ) +{ + init(node, name); +} + +void +KdmItem::init( const TQDomNode &node, const char * ) +{ // Set default layout for every item currentManager = MNone; pos.x = pos.y = 0; @@ -62,7 +80,7 @@ KdmItem::KdmItem( KdmItem *parent, const TQDomNode &node, const char *name ) state = Snormal; // The "toplevel" node (the screen) is really just like a fixed node - if (!parent || !parent->inherits( "KdmItem" )) { + if (!parent() || !parent()->inherits( "KdmItem" )) { setFixedLayout(); return; } @@ -87,7 +105,7 @@ KdmItem::KdmItem( KdmItem *parent, const TQDomNode &node, const char *name ) id = tnode.toElement().attribute( "id", TQString::number( (ulong)this, 16 ) ); // Tell 'parent' to add 'me' to its children - KdmItem *parentItem = static_cast<KdmItem *>( parent ); + KdmItem *parentItem = static_cast<KdmItem *>( parent() ); parentItem->addChildItem( this ); } @@ -195,7 +213,7 @@ KdmItem::setWidget( TQWidget *widget ) if (frame) frame->setFrameStyle( TQFrame::NoFrame ); - myWidget->setGeometry(area); + setGeometry(area, true); connect( myWidget, TQT_SIGNAL(destroyed()), TQT_SLOT(widgetGone()) ); } @@ -236,15 +254,21 @@ KdmItem::setGeometry( const TQRect &newGeometry, bool force ) area = newGeometry; - if (myWidget) - myWidget->setGeometry( newGeometry ); + if (myWidget) { + TQRect widGeo = newGeometry; + if ( widGeo.height() > myWidget->maximumHeight() ) { + widGeo.moveTop( widGeo.top() + ( widGeo.height() - myWidget->maximumHeight() ) / 2 ); + widGeo.setHeight( myWidget->maximumHeight() ); + } + myWidget->setGeometry( widGeo ); + } if (myLayoutItem) myLayoutItem->setGeometry( newGeometry ); // recurr to all boxed children if (boxManager && !boxManager->isEmpty()) boxManager->update( newGeometry, force ); - + // recurr to all fixed children if (fixedManager && !fixedManager->isEmpty()) fixedManager->update( newGeometry, force ); @@ -258,8 +282,16 @@ KdmItem::paint( TQPainter *p, const TQRect &rect ) if (isHidden()) return; - if (myWidget || (myLayoutItem && myLayoutItem->widget())) - return; + if (myWidget || (myLayoutItem && myLayoutItem->widget())) { + // KListView because it's missing a Q_OBJECT + if ( myWidget && myWidget->isA( "KListView" ) ) { + TQPixmap copy( myWidget->size() ); + kdDebug() << myWidget->geometry() << " " << area << " " << myWidget->size() << endl; + bitBlt( ©, TQPoint( 0, 0), p->device(), myWidget->geometry(), Qt::CopyROP ); + myWidget->setPaletteBackgroundPixmap( copy ); + } + return; + } if (area.intersects( rect )) { TQRect contentsRect = area.intersect( rect ); @@ -280,6 +312,8 @@ KdmItem::paint( TQPainter *p, const TQRect &rect ) TQValueList<KdmItem *>::Iterator it; for (it = m_children.begin(); it != m_children.end(); ++it) (*it)->paint( p, rect ); + + } KdmItem *KdmItem::currentActive = 0; @@ -287,8 +321,11 @@ KdmItem *KdmItem::currentActive = 0; void KdmItem::mouseEvent( int x, int y, bool pressed, bool released ) { + if (isShown == ExplicitlyHidden) + return; + if (buttonParent && buttonParent != this) { - buttonParent->mouseEvent( x, y, pressed, released ); + buttonParent->mouseEvent( x, y, pressed, released ); return; } @@ -362,7 +399,8 @@ KdmItem::placementHint( const TQRect &parentRect ) w = parentRect.width(), h = parentRect.height(); - kdDebug() << "KdmItem::placementHint parentRect=" << id << parentRect << " hintedSize=" << hintedSize << endl; + kdDebug() << timestamp() << " KdmItem::placementHint parentRect=" << parentRect << " hintedSize=" << hintedSize << endl; + // check if width or height are set to "box" if (pos.wType == DTbox || pos.hType == DTbox) { if (myLayoutItem || myWidget) @@ -372,7 +410,7 @@ KdmItem::placementHint( const TQRect &parentRect ) return parentRect; boxHint = boxManager->sizeHint(); } - kdDebug() << " => boxHint " << boxHint << endl; + kdDebug() << timestamp() << " boxHint " << boxHint << endl; } if (pos.xType == DTpixel) @@ -380,25 +418,25 @@ KdmItem::placementHint( const TQRect &parentRect ) else if (pos.xType == DTnpixel) x = parentRect.right() - pos.x; else if (pos.xType == DTpercent) - x += int( parentRect.width() / 100.0 * pos.x ); + x += qRound( parentRect.width() / 100.0 * pos.x ); if (pos.yType == DTpixel) y += pos.y; else if (pos.yType == DTnpixel) y = parentRect.bottom() - pos.y; else if (pos.yType == DTpercent) - y += int( parentRect.height() / 100.0 * pos.y ); + y += qRound( parentRect.height() / 100.0 * pos.y ); if (pos.wType == DTpixel) w = pos.width; else if (pos.wType == DTnpixel) w -= pos.width; else if (pos.wType == DTpercent) - w = int( parentRect.width() / 100.0 * pos.width ); + w = qRound( parentRect.width() / 100.0 * pos.width ); else if (pos.wType == DTbox) w = boxHint.width(); else if (hintedSize.width() > 0) - w = hintedSize.width(); + w = hintedSize.width(); else w = 0; @@ -407,14 +445,22 @@ KdmItem::placementHint( const TQRect &parentRect ) else if (pos.hType == DTnpixel) h -= pos.height; else if (pos.hType == DTpercent) - h = int( parentRect.height() / 100.0 * pos.height ); + h = qRound( parentRect.height() / 100.0 * pos.height ); else if (pos.hType == DTbox) h = boxHint.height(); - else if (hintedSize.height() > 0) - h = hintedSize.height(); - else + else if (hintedSize.height() > 0) { + if (w && pos.wType != DTnone) + h = (hintedSize.height() * w) / hintedSize.width(); + else + h = hintedSize.height(); + } else h = 0; + // we choose to take the hinted size, but it's better to listen to the aspect ratio + if (pos.wType == DTnone && pos.hType != DTnone && h && w) { + w = qRound(float(hintedSize.width() * h) / hintedSize.height()); + } + // defaults to center int dx = -w / 2, dy = -h / 2; @@ -430,7 +476,7 @@ KdmItem::placementHint( const TQRect &parentRect ) dx = -w; } // KdmItem *p = static_cast<KdmItem*>( parent() ); - kdDebug() << "KdmItem::placementHint " << id << " x=" << x << " dx=" << dx << " w=" << w << " y=" << y << " dy=" << dy << " h=" << h << " " << parentRect << endl; + kdDebug() << timestamp() << " placementHint " << this << " x=" << x << " dx=" << dx << " w=" << w << " y=" << y << " dy=" << dy << " h=" << h << " " << parentRect << endl; y += dy; x += dx; @@ -529,4 +575,17 @@ KdmItem::setFixedLayout( const TQDomNode &node ) currentManager = MFixed; } +TQWidget * +KdmItem::parentWidget() const +{ + if (myWidget) + return myWidget; + if (!this->parent()) + return 0; + + if (parent()->qt_cast("TQWidget")) + return (TQWidget*)parent(); + return ((KdmItem*)parent())->parentWidget(); +} + #include "kdmitem.moc" diff --git a/kdm/kfrontend/themer/kdmitem.h b/kdm/kfrontend/themer/kdmitem.h index 6a73c889f..98b876977 100644 --- a/kdm/kfrontend/themer/kdmitem.h +++ b/kdm/kfrontend/themer/kdmitem.h @@ -90,6 +90,8 @@ public: * Item constructor and destructor */ KdmItem( KdmItem *parent, const TQDomNode &node = TQDomNode(), const char *name = 0 ); + KdmItem( TQWidget *parent, const TQDomNode &node = TQDomNode(), const char *name = 0 ); // for the root + virtual ~KdmItem(); /** @@ -151,6 +153,7 @@ public: KdmItem *findNode( const TQString &id ) const; virtual void setWidget( TQWidget *widget ); + TQWidget *widget() const { return myWidget; } virtual void setLayoutItem( TQLayoutItem *item ); virtual void hide( bool force = false ); @@ -160,6 +163,9 @@ public: bool isExplicitlyHidden() const { return isShown == ExplicitlyHidden; } TQRect rect() const { return area; } + TQWidget *parentWidget() const; + TQString getId() const { return id; } + signals: void needUpdate( int x, int y, int w, int h ); void activated( const TQString &id ); @@ -237,6 +243,7 @@ protected: void parseColor( const TQString &, TQColor & ); void inheritFromButton( KdmItem *button ); + void init( const TQDomNode &node = TQDomNode(), const char *name = 0 ); TQString itemType, id; TQValueList<KdmItem *> m_children; diff --git a/kdm/kfrontend/themer/kdmlabel.cpp b/kdm/kfrontend/themer/kdmlabel.cpp index 297b7cc48..e83ae9dc7 100644 --- a/kdm/kfrontend/themer/kdmlabel.cpp +++ b/kdm/kfrontend/themer/kdmlabel.cpp @@ -19,8 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include <config.h> #include "kdmlabel.h" -#include <kgreeter.h> +#include "kdmconfig.h" +#include "../kgreeter.h" #include <kglobal.h> #include <klocale.h> @@ -31,6 +33,7 @@ #include <tqpainter.h> #include <tqfontmetrics.h> #include <tqtimer.h> +#include <tqaccel.h> #include <unistd.h> #include <sys/utsname.h> @@ -39,7 +42,7 @@ #endif KdmLabel::KdmLabel( KdmItem *parent, const TQDomNode &node, const char *name ) - : KdmItem( parent, node, name ) + : KdmItem( parent, node, name ), myAccel(0) { itemType = "label"; @@ -92,21 +95,46 @@ KdmLabel::KdmLabel( KdmItem *parent, const TQDomNode &node, const char *name ) } } - // Check if this is a timer label + // Check if this is a timer label) label.isTimer = label.text.find( "%c" ) >= 0; if (label.isTimer) { timer = new TQTimer( this ); timer->start( 1000 ); connect( timer, TQT_SIGNAL(timeout()), TQT_SLOT(update()) ); } - cText = lookupText( label.text ); + setTextInt( lookupText( label.text ) ); +} + +void +KdmLabel::setTextInt( const TQString &txt) +{ + // TODO: catch && + cText = txt; + cAccel = txt.find('&'); + delete myAccel; + myAccel = 0; + if (cAccel != -1) { + cText.remove('&'); + myAccel = new TQAccel(parentWidget()); + myAccel->insertItem(ALT + UNICODE_ACCEL + cText.at(cAccel).lower().unicode()); + connect(myAccel, TQT_SIGNAL(activated(int)), TQT_SLOT(slotAccel())); + } +} + +void +KdmLabel::slotAccel() +{ + if (buttonParent) + emit activated(buttonParent->getId()); + else + emit activated(id); } void KdmLabel::setText( const TQString &txt ) { label.text = txt; - update(); + setTextInt( lookupText( label.text ) ); } QSize @@ -139,7 +167,23 @@ KdmLabel::drawContents( TQPainter *p, const TQRect &/*r*/ ) p->setFont( l->font ); p->setPen( l->color ); //TODO paint clipped (tested but not working..) - p->drawText( area, AlignLeft | SingleLine, cText ); + if (cAccel != -1 && (!id.isEmpty() || buttonParent) ) { + TQString left = cText.left(cAccel); + TQString right = cText.mid(cAccel + 1); + p->drawText( area, AlignLeft | SingleLine, left ); + TQRect tarea = area; + TQFontMetrics fm(l->font); + tarea.rLeft() += fm.width(left); + TQFont f(l->font); + f.setUnderline(true); + p->setFont ( f ); + p->drawText( tarea, AlignLeft | SingleLine, TQString(cText.at(cAccel))); + tarea.rLeft() += fm.width(cText.at(cAccel)); + p->setFont( l->font ); + p->drawText( tarea, AlignLeft | SingleLine, right); + } else { + p->drawText( area, AlignLeft | SingleLine, cText); + } } void @@ -159,7 +203,7 @@ KdmLabel::update() { TQString text = lookupText( label.text ); if (text != cText) { - cText = text; + setTextInt(text); needUpdate(); } } @@ -170,18 +214,20 @@ static const struct { { "language", I18N_NOOP("Language") }, { "session", I18N_NOOP("Session Type") }, { "system", I18N_NOOP("Menu") }, // i18n("Actions"); + { "admin", I18N_NOOP("&Administration") }, { "disconnect", I18N_NOOP("Disconnect") }, { "quit", I18N_NOOP("Quit") }, - { "halt", I18N_NOOP("Power off") }, + { "halt", I18N_NOOP("Power Off") }, { "suspend", I18N_NOOP("Suspend") }, { "reboot", I18N_NOOP("Reboot") }, { "chooser", I18N_NOOP("XDMCP Chooser") }, { "config", I18N_NOOP("Configure") }, - { "caps-lock-warning", I18N_NOOP("You have got caps lock on.") }, + { "caps-lock-warning", I18N_NOOP("Caps Lock is enabled.") }, { "timed-label", I18N_NOOP("User %s will login in %d seconds") }, { "welcome-label", I18N_NOOP("Welcome to %h") }, // _greetString { "username-label", I18N_NOOP("Username:") }, { "password-label", I18N_NOOP("Password:") }, + { "domain-label", I18N_NOOP("Domain:") }, { "login", I18N_NOOP("Login") } }; @@ -195,7 +241,7 @@ KdmLabel::lookupStock( const TQString &stock ) if (type == stocks[i].type) return i18n(stocks[i].text); - kdDebug() << "Invalid <stock> element. Check your theme!" << endl; + kdDebug() << timestamp() << " Invalid <stock> element. Check your theme!" << endl; return stock; } @@ -205,7 +251,6 @@ KdmLabel::lookupText( const TQString &t ) TQString text = t; text.replace( '_', '&' ); -// text.remove( '_' ); // FIXME add key accels, remove underscores for now TQMap<TQChar,TQString> m; struct utsname uts; diff --git a/kdm/kfrontend/themer/kdmlabel.h b/kdm/kfrontend/themer/kdmlabel.h index 0770259c0..1ec2f88ec 100644 --- a/kdm/kfrontend/themer/kdmlabel.h +++ b/kdm/kfrontend/themer/kdmlabel.h @@ -50,6 +50,7 @@ protected: // handle switching between normal / active / prelight configurations virtual void statusChanged(); +public: struct LabelStruct { TQString text; bool isTimer; @@ -67,6 +68,7 @@ protected: public slots: void update(); + void slotAccel(); private: /* Method to lookup the caption associated with an item */ @@ -76,6 +78,10 @@ private: TQString lookupText( const TQString &t ); TQString cText; + int cAccel; + TQAccel *myAccel; + + void setTextInt(const TQString &); }; #endif diff --git a/kdm/kfrontend/themer/kdmlayout.cpp b/kdm/kfrontend/themer/kdmlayout.cpp index 00ca693ae..b17d2e7b7 100644 --- a/kdm/kfrontend/themer/kdmlayout.cpp +++ b/kdm/kfrontend/themer/kdmlayout.cpp @@ -20,6 +20,7 @@ */ #include "kdmlayout.h" +#include "kdmconfig.h" #include "kdmitem.h" #include <kdebug.h> @@ -35,11 +36,11 @@ KdmLayoutFixed::KdmLayoutFixed( const TQDomNode &/*node*/ ) void KdmLayoutFixed::update( const TQRect &parentGeometry, bool force ) { - kdDebug() << "KdmLayoutFixed::update " << parentGeometry << endl; + kdDebug() << timestamp() << " KdmLayoutFixed::update " << parentGeometry << endl; // I can't layout children if the parent rectangle is not valid if (parentGeometry.width() < 0 || parentGeometry.height() < 0) { - kdDebug() << "invalid\n"; + kdDebug() << timestamp() << " invalid\n"; return; } // For each child in list I ask their hinted size and set it! @@ -102,7 +103,7 @@ KdmLayoutBox::update( const TQRect &parentGeometry, bool force ) childrenRect.setTop( childrenRect.top() + height + box.spacing ); } else { TQRect temp( childrenRect.left(), childrenRect.top(), width, childrenRect.height() ); - kdDebug() << "placement " << *it << " " << temp << " " << (*it)->placementHint( temp ) << endl; + kdDebug() << timestamp() << " placement " << *it << " " << temp << " " << (*it)->placementHint( temp ) << endl; temp = (*it)->placementHint( temp ); (*it)->setGeometry( temp, force ); childrenRect.setLeft( childrenRect.left() + width + box.spacing ); @@ -125,7 +126,7 @@ KdmLayoutBox::update( const TQRect &parentGeometry, bool force ) kdDebug() << this << " placementHint " << *it << " " << temp << " " << itemRect << endl; temp.setWidth( itemRect.width() ); childrenRect.setLeft( childrenRect.left() + itemRect.size().width() + box.spacing ); - kdDebug() << "childrenRect after " << *it << " " << childrenRect << endl; + kdDebug() << timestamp() << " childrenRect after " << *it << " " << childrenRect << endl; } itemRect = (*it)->placementHint( temp ); kdDebug() << this << " placementHint2 " << *it << " " << temp << " " << itemRect << endl; diff --git a/kdm/kfrontend/themer/kdmpixmap.cpp b/kdm/kfrontend/themer/kdmpixmap.cpp index 07077e4a1..f18194f53 100644 --- a/kdm/kfrontend/themer/kdmpixmap.cpp +++ b/kdm/kfrontend/themer/kdmpixmap.cpp @@ -22,6 +22,7 @@ #include <config.h> #include "kdmpixmap.h" +#include <kdmconfig.h> #include <kimageeffect.h> #ifdef HAVE_LIBART @@ -29,6 +30,7 @@ #endif #include <kdebug.h> +#include <kstandarddirs.h> #include <tqpainter.h> #include <tqpixmap.h> @@ -58,21 +60,28 @@ KdmPixmap::KdmPixmap( KdmItem *parent, const TQDomNode &node, const char *name ) TQString tagName = el.tagName(); if (tagName == "normal") { - loadPixmap( el.attribute( "file", "" ), pixmap.normal.pixmap, pixmap.normal.fullpath ); + pixmap.normal.fullpath = fullPath( el.attribute( "file", "" ) ); parseColor( el.attribute( "tint", "#ffffff" ), pixmap.normal.tint ); pixmap.normal.alpha = el.attribute( "alpha", "1.0" ).toFloat(); } else if (tagName == "active") { pixmap.active.present = true; - loadPixmap( el.attribute( "file", "" ), pixmap.active.pixmap, pixmap.active.fullpath ); + pixmap.active.fullpath = fullPath( el.attribute( "file", "" ) ); parseColor( el.attribute( "tint", "#ffffff" ), pixmap.active.tint ); pixmap.active.alpha = el.attribute( "alpha", "1.0" ).toFloat(); } else if (tagName == "prelight") { pixmap.prelight.present = true; - loadPixmap( el.attribute( "file", "" ), pixmap.prelight.pixmap, pixmap.prelight.fullpath ); + pixmap.prelight.fullpath = fullPath(el.attribute( "file", "" ) ); parseColor( el.attribute( "tint", "#ffffff" ), pixmap.prelight.tint ); pixmap.prelight.alpha = el.attribute( "alpha", "1.0" ).toFloat(); } } + + // look if we have to have the aspect ratio ready + if (((pos.wType == DTnone && pos.hType != DTnone) || + (pos.wType != DTnone && pos.hType == DTnone) || + (pos.wType == DTnone && pos.hType == DTnone)) && + !pixmap.normal.fullpath.endsWith( ".svg" )) + loadPixmap( &pixmap.normal ); } QSize @@ -100,19 +109,16 @@ KdmPixmap::setGeometry( const TQRect &newGeometry, bool force ) } -void -KdmPixmap::loadPixmap( const TQString &fileName, TQPixmap &map, TQString &fullName ) +TQString +KdmPixmap::fullPath( const TQString &fileName) { - if (fileName.isEmpty()) - return; + if (fileName.isEmpty()) + return TQString::null; - fullName = fileName; + TQString fullName = fileName; if (fullName.at( 0 ) != '/') fullName = baseDir() + "/" + fileName; - - if (!fullName.endsWith( ".svg" )) // we delay it for svgs - if (!map.load( fullName )) - fullName = TQString::null; + return fullName; } void @@ -140,6 +146,25 @@ KdmPixmap::renderSvg( PixmapStruct::PixmapClass *pClass, const TQRect &area ) } void +KdmPixmap::loadPixmap( PixmapStruct::PixmapClass *pClass ) +{ + TQString fullpath = pClass->fullpath; + + kdDebug() << timestamp() << " load " << fullpath << endl; + int index = fullpath.findRev('.'); + TQString ext = fullpath.right(fullpath.length() - index); + fullpath = fullpath.left(index); + kdDebug() << timestamp() << " ext " << ext << " " << fullpath << endl; + TQString testpath = TQString("-%1x%2").arg(area.width()).arg(area.height()) + ext; + kdDebug() << timestamp() << " testing for " << fullpath + testpath << endl; + if (KStandardDirs::exists(fullpath + testpath)) + pClass->pixmap.load(fullpath + testpath); + else + pClass->pixmap.load( fullpath + ext ); + kdDebug() << timestamp() << " done\n"; +} + +void KdmPixmap::drawContents( TQPainter *p, const TQRect &r ) { // choose the correct pixmap class @@ -149,12 +174,20 @@ KdmPixmap::drawContents( TQPainter *p, const TQRect &r ) if (state == Sprelight && pixmap.prelight.present) pClass = &pixmap.prelight; + kdDebug() << "draw " << id << " " << pClass->pixmap.isNull() << endl; + if (pClass->pixmap.isNull()) { - if (pClass->fullpath.isEmpty()) // if neither is set, we're empty + + if (pClass->fullpath.isEmpty()) // if neither is set, we're empty return; - - kdDebug() << "renderSVG\n"; - renderSvg( pClass, area ); + + if (!pClass->fullpath.endsWith( ".svg" ) ) { + loadPixmap(pClass); + } else { + kdDebug() << timestamp() << " renderSVG\n"; + renderSvg( pClass, area ); + kdDebug() << timestamp() << " done\n"; + } } int px = area.left() + r.left(); @@ -176,25 +209,37 @@ KdmPixmap::drawContents( TQPainter *p, const TQRect &r ) if (pClass->readyPixmap.isNull()) { - TQImage scaledImage; + + bool haveTint = pClass->tint.rgb() != 0xFFFFFF; + bool haveAlpha = pClass->alpha < 1.0; + TQImage scaledImage; + // use the loaded pixmap or a scaled version if needed + kdDebug() << timestamp() << " prepare readyPixmap " << pClass->fullpath << " " << area.size() << " " << pClass->pixmap.size() << endl; if (area.size() != pClass->pixmap.size()) { if (pClass->fullpath.endsWith( ".svg" )) { - kdDebug() << "renderSVG\n"; + kdDebug() << timestamp() << " renderSVG\n"; renderSvg( pClass, area ); scaledImage = pClass->pixmap.convertToImage(); } else { - kdDebug() << "convertFromImage\n"; + kdDebug() << timestamp() << " convertFromImage smoothscale\n"; TQImage tempImage = pClass->pixmap.convertToImage(); + kdDebug() << timestamp() << " convertToImage done\n"; scaledImage = tempImage.smoothScale( area.width(), area.height() ); + kdDebug() << timestamp() << " done\n"; } - } else + } else { + if (haveTint || haveAlpha) + { scaledImage = pClass->pixmap.convertToImage(); - - bool haveTint = pClass->tint.rgb() != 0xFFFFFF; - bool haveAlpha = pClass->alpha < 1.0; + // enforce rgba values for the later + scaledImage = scaledImage.convertDepth( 32 ); + } + else + pClass->readyPixmap = pClass->pixmap; + } if (haveTint || haveAlpha) { // blend image(pix) with the given tint @@ -221,9 +266,12 @@ KdmPixmap::drawContents( TQPainter *p, const TQRect &r ) } - pClass->readyPixmap.convertFromImage( scaledImage ); + if (!scaledImage.isNull()) { + kdDebug() << timestamp() << " convertFromImage " << id << " " << area << endl; + pClass->readyPixmap.convertFromImage( scaledImage ); + } } - // kdDebug() << "Pixmap::drawContents " << pClass->readyPixmap.size() << " " << px << " " << py << " " << sx << " " << sy << " " << sw << " " << sh << endl; + kdDebug() << timestamp() << " Pixmap::drawContents " << pClass->readyPixmap.size() << " " << px << " " << py << " " << sx << " " << sy << " " << sw << " " << sh << endl; p->drawPixmap( px, py, pClass->readyPixmap, sx, sy, sw, sh ); } diff --git a/kdm/kfrontend/themer/kdmpixmap.h b/kdm/kfrontend/themer/kdmpixmap.h index 479ef0f8d..92d4895d0 100644 --- a/kdm/kfrontend/themer/kdmpixmap.h +++ b/kdm/kfrontend/themer/kdmpixmap.h @@ -61,9 +61,10 @@ protected: } pixmap; private: - // Method to load the pixmap given by the theme - void loadPixmap( const TQString &fileName, TQPixmap &p, TQString &path ); + // Method to load the pixmap path given by the theme + TQString fullPath( const TQString &fileName ); void renderSvg( PixmapStruct::PixmapClass *pClass, const TQRect &area ); + void loadPixmap( PixmapStruct::PixmapClass *pClass ); }; #endif diff --git a/kdm/kfrontend/themer/kdmrect.cpp b/kdm/kfrontend/themer/kdmrect.cpp index 961809a37..1d854d213 100644 --- a/kdm/kfrontend/themer/kdmrect.cpp +++ b/kdm/kfrontend/themer/kdmrect.cpp @@ -33,6 +33,18 @@ KdmRect::KdmRect( KdmItem *parent, const TQDomNode &node, const char *name ) : KdmItem( parent, node, name ) { + init( node, name ); +} + +KdmRect::KdmRect( TQWidget *parent, const TQDomNode &node, const char *name ) + : KdmItem( parent, node, name ) +{ + init( node, name ); +} + +void +KdmRect::init( const TQDomNode &node, const char * ) +{ itemType = "rect"; // Set default values for rect (note: strings are already Null) @@ -137,13 +149,6 @@ KdmRect::recursiveSetAttribs( TQLayoutItem *li ) } void -KdmRect::setWidget( TQWidget *widget ) -{ - KdmItem::setWidget( widget ); - setAttribs( widget ); -} - -void KdmRect::setLayoutItem( TQLayoutItem *item ) { KdmItem::setLayoutItem( item ); @@ -151,4 +156,17 @@ KdmRect::setLayoutItem( TQLayoutItem *item ) } */ +void +KdmRect::setWidget( TQWidget *widget ) +{ + if ( rect.normal.color.isValid() && widget ) + { + TQPalette p = widget->palette(); + p.setColor( TQPalette::Normal, TQColorGroup::Text, rect.normal.color ); + widget->setPalette(p); + } + KdmItem::setWidget( widget ); + //setAttribs( widget ); +} + #include "kdmrect.moc" diff --git a/kdm/kfrontend/themer/kdmrect.h b/kdm/kfrontend/themer/kdmrect.h index 7e4776233..a505e1921 100644 --- a/kdm/kfrontend/themer/kdmrect.h +++ b/kdm/kfrontend/themer/kdmrect.h @@ -36,6 +36,7 @@ class KdmRect : public KdmItem { public: KdmRect( KdmItem *parent, const TQDomNode &node, const char *name = 0 ); + KdmRect( TQWidget *parent, const TQDomNode &node, const char *name = 0 ); protected: // draw the rect @@ -54,8 +55,9 @@ protected: bool hasBorder; } rect; -// virtual void setWidget( TQWidget *widget ); + virtual void setWidget( TQWidget *widget ); // virtual void setLayoutItem( TQLayoutItem *item ); + void init( const TQDomNode &node, const char *name ); private: void setAttribs( TQWidget *widget ); diff --git a/kdm/kfrontend/themer/kdmthemer.cpp b/kdm/kfrontend/themer/kdmthemer.cpp index aca43e45d..9e6db33db 100644 --- a/kdm/kfrontend/themer/kdmthemer.cpp +++ b/kdm/kfrontend/themer/kdmthemer.cpp @@ -36,11 +36,13 @@ #include <tqfile.h> #include <tqfileinfo.h> -//#include <tqtimer.h> // animation timer - TODO +#include <tqtimer.h> // animation timer - TODO #include <tqobjectlist.h> #include <tqpainter.h> #include <tqwidget.h> #include <tqregion.h> +#include <tqlineedit.h> +#include <tqapplication.h> #include <unistd.h> @@ -72,7 +74,8 @@ KdmThemer::KdmThemer( const TQString &_filename, const TQString &mode, TQWidget return; } // Set the root (screen) item - rootItem = new KdmRect( 0, TQDomNode(), "kdm root" ); + rootItem = new KdmRect( parent, TQDomNode(), "kdm root" ); + connect( rootItem, TQT_SIGNAL(needUpdate( int, int, int, int )), widget(), TQT_SLOT(update( int, int, int, int )) ); @@ -82,6 +85,9 @@ KdmThemer::KdmThemer( const TQString &_filename, const TQString &mode, TQWidget generateItems( rootItem ); connect( rootItem, TQT_SIGNAL(activated( const TQString & )), TQT_SIGNAL(activated( const TQString & )) ); + connect( rootItem, TQT_SIGNAL(activated( const TQString & )), TQT_SLOT(slotActivated( const TQString & )) ); + + TQTimer::singleShot(800, this, TQT_SLOT(slotPaintRoot())); /* *TODO* // Animation timer @@ -151,7 +157,7 @@ KdmThemer::widgetEvent( TQEvent *e ) case TQEvent::Paint: { TQRect paintRect = static_cast<TQPaintEvent *>(e)->rect(); - kdDebug() << "paint on: " << paintRect << endl; + kdDebug() << timestamp() << " paint on: " << paintRect << endl; if (!backBuffer) backBuffer = new TQPixmap( widget()->size() ); @@ -195,7 +201,7 @@ KdmThemer::generateItems( KdmItem *parent, const TQDomNode &node ) // Get its tag, and check it's correct ("greeter") if (theme.tagName() != "greeter") { - kdDebug() << "This does not seem to be a correct theme file." << endl; + kdDebug() << timestamp() << " This does not seem to be a correct theme file." << endl; return; } // Get the list of child nodes @@ -214,6 +220,13 @@ KdmThemer::generateItems( KdmItem *parent, const TQDomNode &node ) if (tagName == "item") { if (!willDisplay( subnode )) continue; + TQString id = el.attribute("id"); + if (id.startsWith("plugin-specific-")) { + id = id.mid(strlen("plugin-specific-")); + if (!_pluginsLogin.contains(id)) + continue; + } + // It's a new item. Draw it TQString type = el.attribute( "type" ); @@ -225,13 +238,11 @@ KdmThemer::generateItems( KdmItem *parent, const TQDomNode &node ) newItem = new KdmPixmap( parent, subnode ); else if (type == "rect") newItem = new KdmRect( parent, subnode ); - else if (type == "entry") { + else if (type == "entry" || type == "list") { newItem = new KdmRect( parent, subnode ); newItem->setType( type ); } // newItem = new KdmEntry( parent, subnode ); - //else if (type=="list") - // newItem = new KdmList( parent, subnode ); else if (type == "svg") newItem = new KdmPixmap( parent, subnode ); if (newItem) { @@ -287,6 +298,11 @@ bool KdmThemer::willDisplay( const TQDomNode &node ) #endif if (type == "halt" || type == "reboot") return _allowShutdown != SHUT_NONE; + else if (type == "userlist") + return _userList; + else if ( type == "!userlist" ) + return !_userList; + // if (type == "system") // return true; @@ -301,7 +317,7 @@ KdmThemer::showStructure( TQObject *obj ) const TQObjectList *wlist = obj->children(); static int counter = 0; if (counter == 0) - kdDebug() << "\n\n<======= Widget tree =================" << endl; + kdDebug() << timestamp() << " \n\n<======= Widget tree =================" << endl; if (wlist) { counter++; TQObjectListIterator it( *wlist ); @@ -323,7 +339,46 @@ KdmThemer::showStructure( TQObject *obj ) counter--; } if (counter == 0) - kdDebug() << "\n\n<======= Widget tree =================\n\n" << endl; + kdDebug() << timestamp() << " \n\n<======= Widget tree =================\n\n" << endl; +} + +void +KdmThemer::slotActivated( const TQString &id ) +{ + TQString toactivate; + if (id == "username-label") + toactivate = "user-entry"; + else if (id == "password-label") + toactivate = "pw-entry"; + else + return; + + KdmItem *item = findNode(toactivate); + if (!item || !item->widget()) + return; + + item->widget()->setFocus(); + TQLineEdit *le = (TQLineEdit*)item->widget()->qt_cast("TQLineEdit"); + if (le) + le->selectAll(); +} + +void +KdmThemer::slotPaintRoot() +{ + KdmItem *back_item = findNode("background"); + if (!back_item) + return; + + TQRect screen = TQApplication::desktop()->screenGeometry(0); + TQPixmap pm(screen.size()); + + TQPainter painter( &pm, true ); + back_item->paint( &painter, back_item->rect()); + painter.end(); + + TQApplication::desktop()->screen()->setErasePixmap(pm); + TQApplication::desktop()->screen()->erase(); } #include "kdmthemer.moc" diff --git a/kdm/kfrontend/themer/kdmthemer.h b/kdm/kfrontend/themer/kdmthemer.h index 6bf6af00d..6dc2318dd 100644 --- a/kdm/kfrontend/themer/kdmthemer.h +++ b/kdm/kfrontend/themer/kdmthemer.h @@ -80,6 +80,10 @@ public: signals: void activated( const TQString &id ); +protected slots: + void slotActivated( const TQString &id ); + void slotPaintRoot(); + private: /* * Our display mode (e.g. console, remote, ...) diff --git a/kdmlib/Makefile.am b/kdmlib/Makefile.am index 91218a8c3..eedb681bc 100644 --- a/kdmlib/Makefile.am +++ b/kdmlib/Makefile.am @@ -1,11 +1,15 @@ AM_CPPFLAGS = -I$(top_srcdir)/kdm/kfrontend $(all_includes) -kde_module_LTLIBRARIES = kgreet_classic.la kgreet_winbind.la +kde_module_LTLIBRARIES = kgreet_classic.la kgreet_pam.la kgreet_winbind.la kgreet_classic_la_SOURCES = kgreet_classic.cpp kgreet_classic_la_LDFLAGS = -module -no-undefined $(KDE_PLUGIN) $(all_libraries) kgreet_classic_la_LIBADD = $(LIB_KDEUI) +kgreet_pam_la_SOURCES = kgreet_pam.cpp +kgreet_pam_la_LDFLAGS = -module -no-undefined $(KDE_PLUGIN) $(all_libraries) +kgreet_pam_la_LIBADD = $(LIB_KDEUI) + kgreet_winbind_la_SOURCES = kgreet_winbind.cpp kgreet_winbind_la_LDFLAGS = -module -no-undefined $(KDE_PLUGIN) $(all_libraries) kgreet_winbind_la_LIBADD = $(LIB_KDEUI) diff --git a/kdmlib/kgreet_pam.cpp b/kdmlib/kgreet_pam.cpp new file mode 100644 index 000000000..b43952488 --- /dev/null +++ b/kdmlib/kgreet_pam.cpp @@ -0,0 +1,668 @@ +/* + +Conversation widget for kdm greeter + +Copyright (C) 2008 Dirk Mueller <[email protected]> + +based on classic kdm greeter: + + Copyright (C) 1997, 1998, 2000 Steffen Hansen <[email protected]> + Copyright (C) 2000-2003 Oswald Buddenhagen <[email protected]> + + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "kgreet_pam.h" +#include "themer/kdmthemer.h" +#include "themer/kdmlabel.h" + +#include <klocale.h> +#include <klineedit.h> +#include <kpassdlg.h> +#include <kuser.h> + +#include <tqregexp.h> +#include <tqlayout.h> +#include <tqlabel.h> +#include <tqtimer.h> + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <syslog.h> + +//#define PAM_GREETER_DEBUG + +class KDMPasswordEdit : public KPasswordEdit { +public: + KDMPasswordEdit( TQWidget *parent ) : KPasswordEdit( parent, 0 ) {} + KDMPasswordEdit( KPasswordEdit::EchoModes echoMode, TQWidget *parent ) : KPasswordEdit( echoMode, parent, 0 ) {} +protected: + virtual void contextMenuEvent( TQContextMenuEvent * ) {} +}; + +static FILE* log; +static void debug(const char* fmt, ...) +{ + va_list lst; + va_start(lst, fmt); + +#ifdef PAM_GREETER_DEBUG +#if 0 + vfprintf(log, fmt, lst); + fflush(log); +#else + char buf[6000]; + sprintf(buf, "*** %s\n", fmt); + vsyslog(LOG_WARNING, buf, lst); +#endif +#endif + va_end(lst); +} + +static KPasswordEdit::EchoModes echoMode; + +KPamGreeter::KPamGreeter( KGreeterPluginHandler *_handler, + KdmThemer *themer, + TQWidget *parent, TQWidget *pred, + const TQString &_fixedEntity, + Function _func, Context _ctx ) : + TQObject(), + KGreeterPlugin( _handler ), + fixedUser( _fixedEntity ), + func( _func ), + ctx( _ctx ), + exp( -1 ), + pExp( -1 ), + running( false ) +{ + ctx = Login; + + debug("KPamGreeter constructed\n"); + + m_parentWidget = parent; + + KdmItem *user_entry = 0, *pw_entry = 0; + int line = 0; + + layoutItem = 0; + + if (themer && + (!(user_entry = themer->findNode( "user-entry" )) || + !(pw_entry = themer->findNode( "pw-entry" )))) + themer = 0; + + m_themer = themer; + + if (!themer) + layoutItem = new TQGridLayout( 0, 0, 10 ); + + loginLabel = 0; + authLabel.clear(); + authEdit.clear(); + loginLabel = 0; + loginEdit = 0; + if (ctx == ExUnlock || ctx == ExChangeTok) + fixedUser = KUser().loginName(); + if (func != ChAuthTok) { + debug("func != ChAuthTok\n"); + debug("fixedUser: *%s*\n", fixedUser.latin1()); + + if (fixedUser.isEmpty()) { + loginEdit = new KLineEdit( parent ); + loginEdit->setContextMenuEnabled( false ); + connect( loginEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotLoginLostFocus()) ); + connect( loginEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) ); + connect( loginEdit, TQT_SIGNAL(textChanged( const TQString & )), TQT_SLOT(slotActivity()) ); + connect( loginEdit, TQT_SIGNAL(selectionChanged()), TQT_SLOT(slotActivity()) ); + if (pred) { + parent->setTabOrder( pred, loginEdit ); + pred = loginEdit; + } + if (!getLayoutItem()) { + loginEdit->adjustSize(); + user_entry->setWidget( loginEdit ); + } else { + loginLabel = new TQLabel( loginEdit, i18n("Username:"), parent ); + getLayoutItem()->addWidget( loginLabel, line, 0 ); + getLayoutItem()->addWidget( loginEdit, line++, 1 ); + } + } else if (ctx != Login && ctx != Shutdown && getLayoutItem()) { + loginLabel = new TQLabel( i18n("Username:"), parent ); + getLayoutItem()->addWidget( loginLabel, line, 0 ); + getLayoutItem()->addWidget( new TQLabel( fixedUser, parent ), line++, 1 ); + } +#if 0 + if (echoMode == -1) + passwdEdit = new KDMPasswordEdit( parent ); + else + passwdEdit = new KDMPasswordEdit( echoMode, + parent ); + connect( passwdEdit, TQT_SIGNAL(textChanged( const TQString & )), + TQT_SLOT(slotActivity()) ); + connect( passwdEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) ); + if (pred) { + parent->setTabOrder( pred, passwdEdit ); + pred = passwdEdit; + } + if (!getLayoutItem()) { + passwdEdit->adjustSize(); + pw_entry->setWidget( passwdEdit ); + } else { + passwdLabel = new TQLabel( passwdEdit, + func == Authenticate ? + i18n("hello &Password:") : + i18n("Current &password:"), + parent ); + getLayoutItem()->addWidget( passwdLabel, line, 0 ); + getLayoutItem()->addWidget( passwdEdit, line++, 1 ); + } +#endif + if (loginEdit) + loginEdit->setFocus(); + } + if (func != Authenticate) { + if (echoMode == -1) { + authEdit << new KDMPasswordEdit( echoMode, parent ); + authEdit << new KDMPasswordEdit( echoMode, parent ); + } else { + authEdit << new KDMPasswordEdit( parent ); + authEdit << new KDMPasswordEdit( parent ); + } + authLabel << new TQLabel( authEdit[0], i18n("&New password:"), parent ); + authLabel << new TQLabel( authEdit[1], i18n("Con&firm password:"), parent ); + if (pred) { + parent->setTabOrder( pred, authEdit[0] ); + parent->setTabOrder( authEdit[0], authEdit[1] ); + } + if (getLayoutItem()) { + getLayoutItem()->addWidget( authLabel[0], line, 0 ); + getLayoutItem()->addWidget( authEdit[0], line++, 1 ); + getLayoutItem()->addWidget( authLabel[1], line, 0 ); + getLayoutItem()->addWidget( authEdit[1], line, 1 ); + } + if (authEdit.size() >= 2) + authEdit[1]->setFocus(); + } +} + +// virtual +KPamGreeter::~KPamGreeter() +{ + debug("KPamGreeter::~KPamGreeter"); + abort(); + if (!layoutItem) { + delete loginEdit; + return; + } + TQLayoutIterator it = static_cast<TQLayout *>(layoutItem)->iterator(); + for (TQLayoutItem *itm = it.current(); itm; itm = ++it) + delete itm->widget(); + delete layoutItem; + debug("destructor finished, good bye"); +} + +void // virtual +KPamGreeter::loadUsers( const TQStringList &users ) +{ + KCompletion *userNamesCompletion = new KCompletion; + userNamesCompletion->setItems( users ); + loginEdit->setCompletionObject( userNamesCompletion ); + loginEdit->setAutoDeleteCompletionObject( true ); + loginEdit->setCompletionMode( KGlobalSettings::CompletionAuto ); +} + +void // virtual +KPamGreeter::presetEntity( const TQString &entity, int field ) +{ + debug("presetEntity(%s,%d) called!\n", entity.latin1(), field); + loginEdit->setText( entity ); + if (field == 1 && authEdit.size() >= 1) + authEdit[0]->setFocus(); + else { + loginEdit->setFocus(); + loginEdit->selectAll(); + if (field == -1 && authEdit.size() >= 1) { + authEdit[0]->setText( " " ); + authEdit[0]->setEnabled( false ); + authTok = false; + } + } + curUser = entity; +} + +TQString // virtual +KPamGreeter::getEntity() const +{ + return fixedUser.isEmpty() ? loginEdit->text() : fixedUser; +} + +void // virtual +KPamGreeter::setUser( const TQString &user ) +{ + // assert( fixedUser.isEmpty() ); + curUser = user; + loginEdit->setText( user ); + if (authEdit.size() >= 1) { + authEdit[0]->setFocus(); + authEdit[0]->selectAll(); + } +} + +void // virtual +KPamGreeter::setEnabled(bool enable) +{ + // assert( !passwd1Label ); + // assert( func == Authenticate && ctx == Shutdown ); +// if (loginLabel) +// loginLabel->setEnabled( enable ); + authEdit[0]->setEnabled( enable ); + setActive( enable ); + if (enable) + authEdit[0]->setFocus(); + } + +void // private +KPamGreeter::returnData() +{ + debug("*************** returnData called with exp %d\n", exp); + + + switch (exp) { + case 0: + handler->gplugReturnText( (loginEdit ? loginEdit->text() : + fixedUser).local8Bit(), + KGreeterPluginHandler::IsUser ); + break; + case 1: + handler->gplugReturnText( authEdit[0]->password(), + KGreeterPluginHandler::IsPassword | + KGreeterPluginHandler::IsSecret ); + break; + case 2: + handler->gplugReturnText( authEdit[1]->password(), + KGreeterPluginHandler::IsSecret ); + break; + default: // case 3: + handler->gplugReturnText( authEdit[2]->password(), + KGreeterPluginHandler::IsNewPassword | + KGreeterPluginHandler::IsSecret ); + break; + } +} + +bool // virtual +KPamGreeter::textMessage( const char *text, bool err ) +{ + debug(" ************** textMessage(%s, %d)\n", text, err); + + if (!authEdit.size()) + return false; + + if (getLayoutItem()) { + TQLabel* label = new TQLabel(TQString::fromUtf8(text), m_parentWidget); + getLayoutItem()->addWidget(label, state+1, 0, 0); + } + + return true; +} + +void // virtual +KPamGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking ) +{ + debug("textPrompt called with prompt %s echo %d nonBlocking %d", prompt, echo, nonBlocking); + debug("state is %d, authEdit.size is %d\n", state, authEdit.size()); + + if (state == 0 && echo) { + if (loginLabel) + loginLabel->setText(TQString::fromUtf8(prompt)); + else if (m_themer) { + KdmLabel *kdmlabel = static_cast<KdmLabel*>(m_themer->findNode("user-label")); + if (kdmlabel) { + //userLabel->setText(TQString::fromUtf8(prompt)); + kdmlabel->label.text = TQString::fromUtf8(prompt); + TQTimer::singleShot(0, kdmlabel, TQT_SLOT(update())); + } + } + } + else if (state >= authEdit.size()) { + if (getLayoutItem()) { + TQLabel* label = new TQLabel(TQString::fromUtf8(prompt), m_parentWidget); + getLayoutItem()->addWidget(label, state+1, 0, 0); + debug("added label widget to layout"); + } + else if (m_themer) { + debug("themer found!"); + KdmItem *pw_label = 0; + + KdmLabel *kdmlabel = static_cast<KdmLabel*>(m_themer->findNode("pw-label")); + if (kdmlabel) { + //userLabel->setText(TQString::fromUtf8(prompt)); + TQString str = TQString::fromUtf8(prompt); + kdmlabel->label.text = str; + TQTimer::singleShot(0, kdmlabel, TQT_SLOT(update())); + } + } + + KDMPasswordEdit* passwdEdit; + + if (echoMode == -1) + passwdEdit = new KDMPasswordEdit( m_parentWidget ); + else + passwdEdit = new KDMPasswordEdit( echoMode, m_parentWidget); + connect( passwdEdit, TQT_SIGNAL(textChanged( const TQString & )), + TQT_SLOT(slotActivity()) ); + connect( passwdEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) ); + authEdit << passwdEdit; + +#if 1 + for(TQValueList<KPasswordEdit*>::iterator it = authEdit.begin(); + it != authEdit.end(); + ++it) { + if ((*it)->isEnabled() && (*it)->text().isEmpty()) { + (*it)->setFocus(); + break; + } + } +#endif + if (getLayoutItem()) + getLayoutItem()->addWidget(passwdEdit, state+1, 1, 0); + + if (m_themer) { + debug("themer found!"); + KdmItem *pw_entry = 0; + + pw_entry = m_themer->findNode("pw-entry"); + + if (pw_entry && passwdEdit) + pw_entry->setWidget(passwdEdit); + + if (0) { + //userLabel->setText(TQString::fromUtf8(prompt)); + //kdmlabel->label.text = TQString::fromUtf8(prompt); + //TQTimer::singleShot(0, kdmlabel, TQT_SLOT(update())); + } + } + else + debug("no themer found!"); + } + ++state; + pExp = exp; + + exp = authEdit.size(); + debug("state %d exp: %d, has %d\n", state, exp, has); + + if (has >= exp || nonBlocking) + returnData(); +} + +bool // virtual +KPamGreeter::binaryPrompt( const char *, bool ) +{ + // this simply cannot happen ... :} + return true; +} + +void // virtual +KPamGreeter::start() +{ + debug("******* start() called\n"); + + while(authEdit.begin() != authEdit.end()) { + KPasswordEdit* item = *authEdit.remove(authEdit.begin()); + delete item; + } + + while(authLabel.begin() != authLabel.end()) { + TQLabel* item = *authLabel.remove(authLabel.begin()); + delete item; + } + + authTok = !(authEdit.size() >= 2 && authEdit[1]->isEnabled()); + exp = has = -1; + state = 0; + running = true; + handler->gplugStart(); +} + +void // virtual +KPamGreeter::suspend() +{ +} + +void // virtual +KPamGreeter::resume() +{ +} + +void // virtual +KPamGreeter::next() +{ + debug("********* next() called state %d\n", state); + + if (state == 0 && running && handler) { + debug(" **** returned text!\n"); + handler->gplugReturnText( (loginEdit ? loginEdit->text() : + fixedUser).local8Bit(), + KGreeterPluginHandler::IsUser ); + setActive(false); + } + + has = 0; + + for(TQValueList<KPasswordEdit*>::iterator it = authEdit.begin(); + it != authEdit.end(); + ++it) { + + has++; + if ((*it)->hasFocus()) { + ++it; + if (it != authEdit.end()) + (*it)->setFocus(); + break; + } + if (it == authEdit.end()) + has = -1; + } + + debug(" has %d and exp %d\n", has, exp); + +#if 0 + // assert( running ); + if (loginEdit && loginEdit->hasFocus()) { + passwdEdit->setFocus(); // will cancel running login if necessary + has = 0; + } else if (passwdEdit && passwdEdit->hasFocus()) { + if (passwd1Edit) + passwd1Edit->setFocus(); + has = 1; + } else if (passwd1Edit) { + if (passwd1Edit->hasFocus()) { + passwd2Edit->setFocus(); + has = 1; // sic! + } else + has = 3; + } else + has = 1; + if (exp < 0) + handler->gplugStart(); +#endif + if (has >= exp) + returnData(); +} + +void // virtual +KPamGreeter::abort() +{ + debug("***** abort() called\n"); + + running = false; + if (exp >= 0) { + exp = -1; + handler->gplugReturnText( 0, 0 ); + } +} + +void // virtual +KPamGreeter::succeeded() +{ + debug("**** succeeded() called\n"); + + // assert( running || timed_login ); + if (!authTok) + setActive( false ); + else + setAllActive( false ); + exp = -1; + running = false; +} + +void // virtual +KPamGreeter::failed() +{ + // assert( running || timed_login ); + setActive( false ); + setAllActive( false ); + exp = -1; + running = false; +} + +#include<assert.h> +void // virtual +KPamGreeter::revive() +{ + // assert( !running ); + setAllActive( true ); + +#if 1 + if (authEdit.size() < 1) + return; +#endif + + assert(authEdit.size() >= 1); + if (authTok) { + authEdit[0]->erase(); + if(authEdit.size() >= 2) + authEdit[1]->erase(); + authEdit[0]->setFocus(); + } else { + authEdit[0]->erase(); + if (loginEdit && loginEdit->isEnabled()) + authEdit[0]->setEnabled( true ); + else { + setActive( true ); + if (loginEdit && loginEdit->text().isEmpty()) + loginEdit->setFocus(); + else + authEdit[0]->setFocus(); + } + } +} + +void // virtual +KPamGreeter::clear() +{ + // assert( !running && !passwd1Edit ); + authEdit[0]->erase(); + if (loginEdit) { + loginEdit->clear(); + loginEdit->setFocus(); + curUser = TQString::null; + } else + authEdit[0]->setFocus(); +} + + +// private + +void +KPamGreeter::setActive( bool enable ) +{ + if (loginEdit) + loginEdit->setEnabled( enable ); +} + +void +KPamGreeter::setAllActive( bool enable ) +{ + for(TQValueList<KPasswordEdit*>::iterator it = authEdit.begin(); + it != authEdit.end(); + ++it) + (*it)->setEnabled( enable ); +} + +void +KPamGreeter::slotLoginLostFocus() +{ + if (!running) + return; + if (exp > 0) { + if (curUser == loginEdit->text()) + return; + exp = -1; + handler->gplugReturnText( 0, 0 ); + } + curUser = loginEdit->text(); + debug("curUser is %s", curUser.latin1()); + handler->gplugSetUser( curUser ); +} + +void +KPamGreeter::slotActivity() +{ + debug("slotActivity"); + + if (running) + handler->gplugActivity(); +} + +// factory + +static bool init( const TQString &, + TQVariant (*getConf)( void *, const char *, const TQVariant & ), + void *ctx ) +{ + echoMode = (KPasswordEdit::EchoModes) getConf( ctx, "EchoMode", TQVariant( -1 ) ).toInt(); + KGlobal::locale()->insertCatalogue( "kgreet_pam" ); + return true; +} + +static void done( void ) +{ + KGlobal::locale()->removeCatalogue( "kgreet_pam" ); + if (log && log != stderr) + fclose(log); + log = 0; +} + +static KGreeterPlugin * +create( KGreeterPluginHandler *handler, KdmThemer *themer, + TQWidget *parent, TQWidget *predecessor, + const TQString &fixedEntity, + KGreeterPlugin::Function func, + KGreeterPlugin::Context ctx ) +{ + return new KPamGreeter( handler, themer, parent, predecessor, fixedEntity, func, ctx ); +} + +KDE_EXPORT kgreeterplugin_info kgreeterplugin_info = { + I18N_NOOP("Pam conversation plugin"), "pam", + kgreeterplugin_info::Local | kgreeterplugin_info::Presettable, + init, done, create +}; + +#include "kgreet_pam.moc" diff --git a/kdmlib/kgreet_pam.h b/kdmlib/kgreet_pam.h new file mode 100644 index 000000000..f0bea7d02 --- /dev/null +++ b/kdmlib/kgreet_pam.h @@ -0,0 +1,93 @@ +/* + +Conversation widget for kdm greeter + +Copyright (C) 2008 Dirk Mueller <[email protected]> + + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#ifndef KGREET_CLASSIC_H +#define KGREET_CLASSIC_H + +#include "kgreeterplugin.h" + +#include <tqobject.h> +#include <tqlayout.h> + +class KLineEdit; +class KPasswordEdit; +class KSimpleConfig; +class TQGridLayout; +class TQLabel; + +class KPamGreeter : public TQObject, public KGreeterPlugin { + Q_OBJECT + + public: + KPamGreeter( KGreeterPluginHandler *handler, + KdmThemer *themer, + TQWidget *parent, TQWidget *predecessor, + const TQString &fixedEntitiy, + Function func, Context ctx ); + ~KPamGreeter(); + virtual void loadUsers( const TQStringList &users ); + virtual void presetEntity( const TQString &entity, int field ); + virtual TQString getEntity() const; + virtual void setUser( const TQString &user ); + virtual void setEnabled( bool on ); + virtual bool textMessage( const char *message, bool error ); + virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking ); + virtual bool binaryPrompt( const char *prompt, bool nonBlocking ); + virtual void start(); + virtual void suspend(); + virtual void resume(); + virtual void next(); + virtual void abort(); + virtual void succeeded(); + virtual void failed(); + virtual void revive(); + virtual void clear(); + + TQGridLayout *getLayoutItem() const { return static_cast<TQGridLayout*>(layoutItem); } + + public slots: + void slotLoginLostFocus(); + void slotActivity(); + + private: + void setActive( bool enable ); + void setAllActive( bool enable ); + void returnData(); + + TQLabel *loginLabel; + TQValueList<TQLabel*> authLabel; + KLineEdit *loginEdit; + TQWidget* m_parentWidget; + TQValueList<KPasswordEdit*> authEdit; + KSimpleConfig *stsFile; + KdmThemer *m_themer; + TQString fixedUser, curUser; + Function func; + Context ctx; + int exp, pExp, has; + unsigned state; + bool running, authTok; +}; + +#endif /* KGREET_CLASSIC_H */ diff --git a/khelpcenter/kcmhelpcenter.cpp b/khelpcenter/kcmhelpcenter.cpp index c3b3e3094..aadce700a 100644 --- a/khelpcenter/kcmhelpcenter.cpp +++ b/khelpcenter/kcmhelpcenter.cpp @@ -321,6 +321,7 @@ bool KCMHelpCenter::save() void KCMHelpCenter::load() { + findWriteableIndexDir(); mIndexDirLabel->setText( Prefs::indexDirectory() ); mListView->clear(); @@ -675,6 +676,12 @@ void KCMHelpCenter::checkSelection() enableButtonOK( count != 0 ); } +void KCMHelpCenter::findWriteableIndexDir() +{ + TQFileInfo currentDir( Prefs::indexDirectory() ); + if ( !currentDir.isWritable() ) + Prefs::setIndexDirectory( KGlobal::dirs()->saveLocation("data", "khelpcenter/index/") ); +} #include "kcmhelpcenter.moc" // vim:ts=2:sw=2:et diff --git a/khelpcenter/kcmhelpcenter.h b/khelpcenter/kcmhelpcenter.h index 4715d1a0a..8bf2f3b6c 100644 --- a/khelpcenter/kcmhelpcenter.h +++ b/khelpcenter/kcmhelpcenter.h @@ -146,6 +146,11 @@ class KCMHelpCenter : public KDialogBase, virtual public KCMHelpCenterIface void advanceProgress(); + /** + * Find a user-writeable location for the indices, if the current location + * is not. + */ + void findWriteableIndexDir(); private: KHC::SearchEngine *mEngine; diff --git a/khelpcenter/navigator.cpp b/khelpcenter/navigator.cpp index 48ae76dd0..ad308cfc6 100644 --- a/khelpcenter/navigator.cpp +++ b/khelpcenter/navigator.cpp @@ -120,8 +120,6 @@ Navigator::Navigator( View *view, TQWidget *parent, const char *name ) mTabWidget = new TQTabWidget( this ); topLayout->addWidget( mTabWidget ); - connect( mTabWidget, TQT_SIGNAL( currentChanged( TQWidget * ) ), - TQT_SLOT( slotTabChanged( TQWidget * ) ) ); setupContentsTab(); setupGlossaryTab(); @@ -135,6 +133,9 @@ Navigator::Navigator( View *view, TQWidget *parent, const char *name ) mSearchWidget->updateScopeList(); mSearchWidget->readConfig( KGlobal::config() ); } + + connect( mTabWidget, TQT_SIGNAL( currentChanged( QWidget * ) ), + TQT_SLOT( slotTabChanged( QWidget * ) ) ); } Navigator::~Navigator() @@ -336,6 +337,11 @@ void Navigator::selectItem( const KURL &url ) item = item->nextSibling() ) { NavigatorAppItem *appItem = dynamic_cast<NavigatorAppItem *>( item ); if ( appItem ) appItem->populate( true /* recursive */ ); + for ( QListViewItem *subitem = item->firstChild(); subitem; + subitem = subitem->nextSibling() ) { + appItem = dynamic_cast<NavigatorAppItem *>( subitem ); + if ( appItem ) appItem->populate( true /* recursive */ ); + } } } diff --git a/khelpcenter/searchhandlers/Makefile.am b/khelpcenter/searchhandlers/Makefile.am index 65f4060b6..f2ebd57ff 100644 --- a/khelpcenter/searchhandlers/Makefile.am +++ b/khelpcenter/searchhandlers/Makefile.am @@ -3,7 +3,7 @@ searchhandlers_DATA = htdig.desktop man.desktop docbook.desktop searchhandlersdir = $(kde_datadir)/khelpcenter/searchhandlers kde_bin_SCRIPTS = khc_htdig.pl khc_htsearch.pl khc_mansearch.pl \ - khc_docbookdig.pl + khc_docbookdig.pl khc_beagle_search.pl khc_beagle_index.pl htdigdata_DATA = htdig_long.html diff --git a/khelpcenter/searchhandlers/docbook.desktop b/khelpcenter/searchhandlers/docbook.desktop index 08208c187..5c6d11284 100644 --- a/khelpcenter/searchhandlers/docbook.desktop +++ b/khelpcenter/searchhandlers/docbook.desktop @@ -2,5 +2,5 @@ DocumentTypes=text/docbook -SearchCommand=khc_htsearch.pl --docbook --indexdir=%d --config=%i --words=%w --method=%o --maxnum=%m --lang=en -IndexCommand=khc_docbookdig.pl --indexdir=%d --docpath=%p --identifier=%i +SearchCommand=khc_beagle_search.pl --method=%o --maxnum=%m %w +IndexCommand=khc_beagle_index.pl %d %i diff --git a/khelpcenter/searchhandlers/khc_beagle_index.pl b/khelpcenter/searchhandlers/khc_beagle_index.pl new file mode 100644 index 000000000..02f1b9330 --- /dev/null +++ b/khelpcenter/searchhandlers/khc_beagle_index.pl @@ -0,0 +1,49 @@ +#!/usr/bin/perl +# vim:sw=4:et + +use warnings; + +sub getKDEDocDir() +{ + my $prefix = `kde-config --prefix`; + chomp $prefix; + + $prefix = "/opt/kde" if (not defined($prefix)); + return "$prefix/share/doc"; +} + +sub addRoot() +{ + my $kdedocdir = &getKDEDocDir; + + open (IN, "-|") || exec "beagle-config", "indexing", "ListRoots"; + + my $kdedoc_found = 0; + while(<IN>) { + if (/^$kdedocdir/o) { + $kdedoc_found = 1; + last; + } + } + close(IN); + + if (not $kdedoc_found) { + `beagle-config indexing AddRoot $kdedocdir`; + `beagle-config indexing AddRoot $kdedocdir-bundle`; + } +} + +sub createExistsFile($$) +{ + my ($idir, $ident) = @_; + + open(OUT, ">", "$idir/$idir"); + close(OUT); +} + +my $idir = $ARGV[0]; +my $ident = $ARGV[1]; + +if (addRoot) { + createExistsFile($idir, $ident); +} diff --git a/khelpcenter/searchhandlers/khc_beagle_search.pl b/khelpcenter/searchhandlers/khc_beagle_search.pl new file mode 100644 index 000000000..d7a1f44b8 --- /dev/null +++ b/khelpcenter/searchhandlers/khc_beagle_search.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl -w +# vim:sw=4:et + +use warnings; +use strict; +use Getopt::Long; + +sub isBeagleRunning() +{ + open(IN, "-|") || exec "beagle-ping"; + while(<IN>) { + if (/^Daemon version:/) { + close(IN); + return 1; + } + } + close(IN); + return 0; +} + +sub formatHTML($$) +{ + my ($query, $hits) = @_; + + print "<html>\n<body\n<ul>\n"; + + foreach my $hit(@$hits) { + print "<li>$hit</li>\n"; + } + print "</ul>\n</body>\n</html>\n"; +} + +sub beagleQuery($$$) +{ + my ($words, $method, $maxnum) = @_; + + my @hits = (); + + open(IN, "-|") || exec "beagle-query", "--type", "DocbookEntry", "--type", "File", "--max-hits", $maxnum, @$words, "ext:docbook"; + while(<IN>) { + chop; + next if (/^Debug:/); + + my $uri = $_; + $uri = $1 if ($uri =~ /^file:\/\/(.*)$/); + + print "uri: $uri\n"; + my $helpLink = &makeHelpLink($uri); + + push(@hits, $helpLink) if (!grep { /^$helpLink$/ } @hits); + } + close(IN); + return @hits; +} + +sub makeHelpLink($) +{ + # Try to figure out the name of the application from the path to its index.docbook file + + my ($path) = @_; + my @pathcomponents = split '/', $path; + + my $appName = $pathcomponents[-2]; + my $appName2 = $pathcomponents[-3]; + + if ($appName eq $appName2 or $appName2 eq "doc" + or (-d "/usr/share/locale/$appName2")) { + return "<a href=\"help:/$appName\">$appName</a>"; + } + return "<a href=\"help:/$appName2/$appName\">$appName ($appName2)</a>"; +} + +my $method = "and"; +my $maxnum = 100; + +GetOptions("method=s", \$method, "maxnum=i", \$maxnum); + +my @hits = ("The Beagle daemon is not running, search is not available"); + +my @words = @ARGV; + +if (isBeagleRunning()) { + @hits = beagleQuery(\@words, $method, $maxnum); +} + +@hits = ("There are no search results") if ($#hits < 0); + +formatHTML(\@words, \@hits); diff --git a/kicker/applets/systemtray/systemtrayapplet.cpp b/kicker/applets/systemtray/systemtrayapplet.cpp index 933855f74..51bf2b9d8 100644 --- a/kicker/applets/systemtray/systemtrayapplet.cpp +++ b/kicker/applets/systemtray/systemtrayapplet.cpp @@ -189,6 +189,7 @@ bool SystemTrayApplet::x11Event( XEvent *e ) if( isWinManaged( (WId)e->xclient.data.l[2] ) ) // we already manage it return true; embedWindow( e->xclient.data.l[2], false ); + updateVisibleWins(); layoutTray(); return true; } @@ -215,13 +216,12 @@ void SystemTrayApplet::preferences() connect(m_settingsDialog, TQT_SIGNAL(finished()), this, TQT_SLOT(settingsDialogFinished())); m_iconSelector = new KActionSelector(m_settingsDialog); - m_iconSelector->setAvailableLabel(i18n("Visible icons:")); - m_iconSelector->setSelectedLabel(i18n("Hidden icons:")); - m_iconSelector->setShowUpDownButtons(false); + m_iconSelector->setAvailableLabel(i18n("Hidden icons:")); + m_iconSelector->setSelectedLabel(i18n("Visible icons:")); m_settingsDialog->setMainWidget(m_iconSelector); - TQListBox *shownListBox = m_iconSelector->availableListBox(); - TQListBox *hiddenListBox = m_iconSelector->selectedListBox(); + TQListBox *hiddenListBox = m_iconSelector->availableListBox(); + TQListBox *shownListBox = m_iconSelector->selectedListBox(); TrayEmbedList::const_iterator it = m_shownWins.begin(); TrayEmbedList::const_iterator itEnd = m_shownWins.end(); @@ -263,26 +263,48 @@ void SystemTrayApplet::applySettings() } KConfig *conf = config(); - conf->setGroup("HiddenTrayIcons"); - TQString name; - - // use the following snippet of code someday to implement ordering - // of icons - /* - m_visibleIconList.clear(); - TQListBoxItem* item = m_iconSelector->availableListBox()->firstItem(); - for (; item; item = item->next()) + + // Save the sort order and hidden status using the window class (WM_CLASS) rather + // than window name (caption) - window name is i18n-ed, so it's for example + // not possible to create default settings. + // For backwards compatibility, name is kept as it is, class is preceded by '!'. + TQMap< TQString, TQString > windowNameToClass; + for( TrayEmbedList::ConstIterator it = m_shownWins.begin(); + it != m_shownWins.end(); + ++it ) { + KWin::WindowInfo info = KWin::windowInfo( (*it)->embeddedWinId(), NET::WMName, NET::WM2WindowClass); + windowNameToClass[ info.name() ] = '!' + info.windowClassClass(); + } + for( TrayEmbedList::ConstIterator it = m_hiddenWins.begin(); + it != m_hiddenWins.end(); + ++it ) { + KWin::WindowInfo info = KWin::windowInfo( (*it)->embeddedWinId(), NET::WMName, NET::WM2WindowClass); + windowNameToClass[ info.name() ] = '!' + info.windowClassClass(); + } + + conf->setGroup("SortedTrayIcons"); + m_sortOrderIconList.clear(); + for(TQListBoxItem* item = m_iconSelector->selectedListBox()->firstItem(); + item; + item = item->next()) { - m_visibleIconList.append(item->text()); + if( windowNameToClass.contains(item->text())) + m_sortOrderIconList.append(windowNameToClass[item->text()]); + else + m_sortOrderIconList.append(item->text()); } - conf->writeEntry("Visible", m_visibleIconList); - selection.clear();*/ + conf->writeEntry("SortOrder", m_sortOrderIconList); + conf->setGroup("HiddenTrayIcons"); m_hiddenIconList.clear(); - TQListBoxItem* item = m_iconSelector->selectedListBox()->firstItem(); - for (; item; item = item->next()) + for(TQListBoxItem* item = m_iconSelector->availableListBox()->firstItem(); + item; + item = item->next()) { - m_hiddenIconList.append(item->text()); + if( windowNameToClass.contains(item->text())) + m_hiddenIconList.append(windowNameToClass[item->text()]); + else + m_hiddenIconList.append(item->text()); } conf->writeEntry("Hidden", m_hiddenIconList); conf->sync(); @@ -437,6 +459,9 @@ void SystemTrayApplet::loadSettings() conf->setGroup("HiddenTrayIcons"); m_hiddenIconList = conf->readListEntry("Hidden"); + conf->setGroup("SortedTrayIcons"); + m_sortOrderIconList = conf->readListEntry("SortOrder"); + //Note This setting comes from kdeglobal. conf->setGroup("System Tray"); m_iconSize = conf->readNumEntry("systrayIconWidth", 22); @@ -526,7 +551,9 @@ bool SystemTrayApplet::isWinManaged(WId w) bool SystemTrayApplet::shouldHide(WId w) { - return m_hiddenIconList.find(KWin::windowInfo(w).name()) != m_hiddenIconList.end(); + return m_hiddenIconList.find(KWin::windowInfo(w).name()) != m_hiddenIconList.end() + || m_hiddenIconList.find('!'+KWin::windowInfo(w,0,NET::WM2WindowClass).windowClassClass()) + != m_hiddenIconList.end(); } void SystemTrayApplet::updateVisibleWins() @@ -549,6 +576,35 @@ void SystemTrayApplet::updateVisibleWins() (*emb)->hide(); } } + + TQMap< QXEmbed*, TQString > names; // cache window names and classes + TQMap< QXEmbed*, TQString > classes; + for( TrayEmbedList::const_iterator it = m_shownWins.begin(); + it != m_shownWins.end(); + ++it ) { + KWin::WindowInfo info = KWin::windowInfo((*it)->embeddedWinId(),NET::WMName,NET::WM2WindowClass); + names[ *it ] = info.name(); + classes[ *it ] = '!'+info.windowClassClass(); + } + TrayEmbedList newList; + for( TQStringList::const_iterator it1 = m_sortOrderIconList.begin(); + it1 != m_sortOrderIconList.end(); + ++it1 ) { + for( TrayEmbedList::iterator it2 = m_shownWins.begin(); + it2 != m_shownWins.end(); + ) { + if( (*it1).startsWith("!") ? classes[ *it2 ] == *it1 : names[ *it2 ] == *it1 ) { + newList.append( *it2 ); // don't bail out, there may be multiple ones + it2 = m_shownWins.erase( it2 ); + } else + ++it2; + } + } + for( TrayEmbedList::const_iterator it = m_shownWins.begin(); + it != m_shownWins.end(); + ++it ) + newList.append( *it ); // append unsorted items + m_shownWins = newList; } void SystemTrayApplet::toggleExpanded() diff --git a/kicker/applets/systemtray/systemtrayapplet.h b/kicker/applets/systemtray/systemtrayapplet.h index a92b8f74e..f66e0caa5 100644 --- a/kicker/applets/systemtray/systemtrayapplet.h +++ b/kicker/applets/systemtray/systemtrayapplet.h @@ -98,6 +98,7 @@ private: TrayEmbedList m_shownWins; TrayEmbedList m_hiddenWins; TQStringList m_hiddenIconList; + TQStringList m_sortOrderIconList; KWinModule *kwin_module; Atom net_system_tray_selection; Atom net_system_tray_opcode; diff --git a/kicker/data/kickoff/button-box-gradient-topdown.png b/kicker/data/kickoff/button-box-gradient-topdown.png Binary files differnew file mode 100644 index 000000000..378816342 --- /dev/null +++ b/kicker/data/kickoff/button-box-gradient-topdown.png diff --git a/kicker/data/kickoff/button-box-gradient.png b/kicker/data/kickoff/button-box-gradient.png Binary files differnew file mode 100644 index 000000000..a7c11adba --- /dev/null +++ b/kicker/data/kickoff/button-box-gradient.png diff --git a/kicker/data/kickoff/button-box-left-corner.png b/kicker/data/kickoff/button-box-left-corner.png Binary files differnew file mode 100644 index 000000000..c4080cb00 --- /dev/null +++ b/kicker/data/kickoff/button-box-left-corner.png diff --git a/kicker/data/kickoff/button-box-left.png b/kicker/data/kickoff/button-box-left.png Binary files differnew file mode 100644 index 000000000..3b532f8bd --- /dev/null +++ b/kicker/data/kickoff/button-box-left.png diff --git a/kicker/data/kickoff/button-box-right-corner.png b/kicker/data/kickoff/button-box-right-corner.png Binary files differnew file mode 100644 index 000000000..ef44b1fab --- /dev/null +++ b/kicker/data/kickoff/button-box-right-corner.png diff --git a/kicker/data/kickoff/button-box-top.png b/kicker/data/kickoff/button-box-top.png Binary files differnew file mode 100644 index 000000000..1cac298be --- /dev/null +++ b/kicker/data/kickoff/button-box-top.png diff --git a/kicker/data/kickoff/cr128-action-suspend2disk.png b/kicker/data/kickoff/cr128-action-suspend2disk.png Binary files differnew file mode 100644 index 000000000..b3ac2fe05 --- /dev/null +++ b/kicker/data/kickoff/cr128-action-suspend2disk.png diff --git a/kicker/data/kickoff/cr128-action-suspend2ram.png b/kicker/data/kickoff/cr128-action-suspend2ram.png Binary files differnew file mode 100644 index 000000000..9e641bd47 --- /dev/null +++ b/kicker/data/kickoff/cr128-action-suspend2ram.png diff --git a/kicker/data/kickoff/cr16-action-suspend2disk.png b/kicker/data/kickoff/cr16-action-suspend2disk.png Binary files differnew file mode 100644 index 000000000..a28ab8ad9 --- /dev/null +++ b/kicker/data/kickoff/cr16-action-suspend2disk.png diff --git a/kicker/data/kickoff/cr16-action-suspend2ram.png b/kicker/data/kickoff/cr16-action-suspend2ram.png Binary files differnew file mode 100644 index 000000000..45738ccc5 --- /dev/null +++ b/kicker/data/kickoff/cr16-action-suspend2ram.png diff --git a/kicker/data/kickoff/cr32-action-leave.png b/kicker/data/kickoff/cr32-action-leave.png Binary files differnew file mode 100644 index 000000000..89dc15953 --- /dev/null +++ b/kicker/data/kickoff/cr32-action-leave.png diff --git a/kicker/data/kickoff/cr32-action-suspend2disk.png b/kicker/data/kickoff/cr32-action-suspend2disk.png Binary files differnew file mode 100644 index 000000000..7bcb027b1 --- /dev/null +++ b/kicker/data/kickoff/cr32-action-suspend2disk.png diff --git a/kicker/data/kickoff/cr32-action-suspend2ram.png b/kicker/data/kickoff/cr32-action-suspend2ram.png Binary files differnew file mode 100644 index 000000000..7a96cd24f --- /dev/null +++ b/kicker/data/kickoff/cr32-action-suspend2ram.png diff --git a/kicker/data/kickoff/cr48-action-leave.png b/kicker/data/kickoff/cr48-action-leave.png Binary files differnew file mode 100644 index 000000000..7c01634b9 --- /dev/null +++ b/kicker/data/kickoff/cr48-action-leave.png diff --git a/kicker/data/kickoff/cr48-action-suspend2disk.png b/kicker/data/kickoff/cr48-action-suspend2disk.png Binary files differnew file mode 100644 index 000000000..9ff2148b8 --- /dev/null +++ b/kicker/data/kickoff/cr48-action-suspend2disk.png diff --git a/kicker/data/kickoff/cr48-action-suspend2ram.png b/kicker/data/kickoff/cr48-action-suspend2ram.png Binary files differnew file mode 100644 index 000000000..2aefa6ce4 --- /dev/null +++ b/kicker/data/kickoff/cr48-action-suspend2ram.png diff --git a/kicker/data/kickoff/cr48-app-recently_used.png b/kicker/data/kickoff/cr48-app-recently_used.png Binary files differnew file mode 100644 index 000000000..b97479759 --- /dev/null +++ b/kicker/data/kickoff/cr48-app-recently_used.png diff --git a/kicker/data/kickoff/cr64-action-suspend2disk.png b/kicker/data/kickoff/cr64-action-suspend2disk.png Binary files differnew file mode 100644 index 000000000..f6e57d786 --- /dev/null +++ b/kicker/data/kickoff/cr64-action-suspend2disk.png diff --git a/kicker/data/kickoff/cr64-action-suspend2ram.png b/kicker/data/kickoff/cr64-action-suspend2ram.png Binary files differnew file mode 100644 index 000000000..cdb47d04f --- /dev/null +++ b/kicker/data/kickoff/cr64-action-suspend2ram.png diff --git a/kicker/data/kickoff/crsc-action-leave.svgz b/kicker/data/kickoff/crsc-action-leave.svgz Binary files differnew file mode 100644 index 000000000..b6a93b05c --- /dev/null +++ b/kicker/data/kickoff/crsc-action-leave.svgz diff --git a/kicker/data/kickoff/crsc-action-suspend2disk.svgz b/kicker/data/kickoff/crsc-action-suspend2disk.svgz Binary files differnew file mode 100644 index 000000000..d73b491d9 --- /dev/null +++ b/kicker/data/kickoff/crsc-action-suspend2disk.svgz diff --git a/kicker/data/kickoff/crsc-action-suspend2ram.svgz b/kicker/data/kickoff/crsc-action-suspend2ram.svgz Binary files differnew file mode 100644 index 000000000..c38d2ed33 --- /dev/null +++ b/kicker/data/kickoff/crsc-action-suspend2ram.svgz diff --git a/kicker/data/kickoff/kmenu_active.png b/kicker/data/kickoff/kmenu_active.png Binary files differnew file mode 100644 index 000000000..fa5ae4de1 --- /dev/null +++ b/kicker/data/kickoff/kmenu_active.png diff --git a/kicker/data/kickoff/kmenu_basic.mng b/kicker/data/kickoff/kmenu_basic.mng Binary files differnew file mode 100644 index 000000000..4cea61fff --- /dev/null +++ b/kicker/data/kickoff/kmenu_basic.mng diff --git a/kicker/data/kickoff/kmenu_flipped.mng b/kicker/data/kickoff/kmenu_flipped.mng Binary files differnew file mode 100644 index 000000000..2b78b4007 --- /dev/null +++ b/kicker/data/kickoff/kmenu_flipped.mng diff --git a/kicker/data/kickoff/kmenu_vertical.mng b/kicker/data/kickoff/kmenu_vertical.mng Binary files differnew file mode 100644 index 000000000..9cd3aac2b --- /dev/null +++ b/kicker/data/kickoff/kmenu_vertical.mng diff --git a/kicker/data/kickoff/left_triangle.png b/kicker/data/kickoff/left_triangle.png Binary files differnew file mode 100644 index 000000000..b8ac404fd --- /dev/null +++ b/kicker/data/kickoff/left_triangle.png diff --git a/kicker/data/kickoff/main_border_bc.png b/kicker/data/kickoff/main_border_bc.png Binary files differnew file mode 100644 index 000000000..05e497763 --- /dev/null +++ b/kicker/data/kickoff/main_border_bc.png diff --git a/kicker/data/kickoff/main_border_lc.png b/kicker/data/kickoff/main_border_lc.png Binary files differnew file mode 100644 index 000000000..c440e859e --- /dev/null +++ b/kicker/data/kickoff/main_border_lc.png diff --git a/kicker/data/kickoff/main_border_rc.png b/kicker/data/kickoff/main_border_rc.png Binary files differnew file mode 100644 index 000000000..6cef8af01 --- /dev/null +++ b/kicker/data/kickoff/main_border_rc.png diff --git a/kicker/data/kickoff/main_border_tc.png b/kicker/data/kickoff/main_border_tc.png Binary files differnew file mode 100644 index 000000000..bc03e85dd --- /dev/null +++ b/kicker/data/kickoff/main_border_tc.png diff --git a/kicker/data/kickoff/main_corner_bl.png b/kicker/data/kickoff/main_corner_bl.png Binary files differnew file mode 100644 index 000000000..32ea680f1 --- /dev/null +++ b/kicker/data/kickoff/main_corner_bl.png diff --git a/kicker/data/kickoff/main_corner_br.png b/kicker/data/kickoff/main_corner_br.png Binary files differnew file mode 100644 index 000000000..b2d898ab6 --- /dev/null +++ b/kicker/data/kickoff/main_corner_br.png diff --git a/kicker/data/kickoff/main_corner_tl.png b/kicker/data/kickoff/main_corner_tl.png Binary files differnew file mode 100644 index 000000000..11fe645ce --- /dev/null +++ b/kicker/data/kickoff/main_corner_tl.png diff --git a/kicker/data/kickoff/main_corner_tr.png b/kicker/data/kickoff/main_corner_tr.png Binary files differnew file mode 100644 index 000000000..a439d9763 --- /dev/null +++ b/kicker/data/kickoff/main_corner_tr.png diff --git a/kicker/data/kickoff/menu_separator.png b/kicker/data/kickoff/menu_separator.png Binary files differnew file mode 100644 index 000000000..2ba13727d --- /dev/null +++ b/kicker/data/kickoff/menu_separator.png diff --git a/kicker/data/kickoff/resize_handle.png b/kicker/data/kickoff/resize_handle.png Binary files differnew file mode 100644 index 000000000..c0811dc50 --- /dev/null +++ b/kicker/data/kickoff/resize_handle.png diff --git a/kicker/data/kickoff/right_triangle.png b/kicker/data/kickoff/right_triangle.png Binary files differnew file mode 100644 index 000000000..9766030c0 --- /dev/null +++ b/kicker/data/kickoff/right_triangle.png diff --git a/kicker/data/kickoff/search-gradient-topdown.png b/kicker/data/kickoff/search-gradient-topdown.png Binary files differnew file mode 100644 index 000000000..b13a19290 --- /dev/null +++ b/kicker/data/kickoff/search-gradient-topdown.png diff --git a/kicker/data/kickoff/search-gradient.png b/kicker/data/kickoff/search-gradient.png Binary files differnew file mode 100644 index 000000000..3478ea18b --- /dev/null +++ b/kicker/data/kickoff/search-gradient.png diff --git a/kicker/data/kickoff/search-running.mng b/kicker/data/kickoff/search-running.mng Binary files differnew file mode 100644 index 000000000..9f477c9c3 --- /dev/null +++ b/kicker/data/kickoff/search-running.mng diff --git a/kicker/data/kickoff/search-tab-center.png b/kicker/data/kickoff/search-tab-center.png Binary files differnew file mode 100644 index 000000000..26ec2f2e9 --- /dev/null +++ b/kicker/data/kickoff/search-tab-center.png diff --git a/kicker/data/kickoff/search-tab-left.png b/kicker/data/kickoff/search-tab-left.png Binary files differnew file mode 100644 index 000000000..507b41767 --- /dev/null +++ b/kicker/data/kickoff/search-tab-left.png diff --git a/kicker/data/kickoff/search-tab-right.png b/kicker/data/kickoff/search-tab-right.png Binary files differnew file mode 100644 index 000000000..94a410443 --- /dev/null +++ b/kicker/data/kickoff/search-tab-right.png diff --git a/kicker/data/kickoff/search-tab-top-center.png b/kicker/data/kickoff/search-tab-top-center.png Binary files differnew file mode 100644 index 000000000..51482ad23 --- /dev/null +++ b/kicker/data/kickoff/search-tab-top-center.png diff --git a/kicker/data/kickoff/search-tab-top-left.png b/kicker/data/kickoff/search-tab-top-left.png Binary files differnew file mode 100644 index 000000000..97264782a --- /dev/null +++ b/kicker/data/kickoff/search-tab-top-left.png diff --git a/kicker/data/kickoff/search-tab-top-right.png b/kicker/data/kickoff/search-tab-top-right.png Binary files differnew file mode 100644 index 000000000..fc80f40c2 --- /dev/null +++ b/kicker/data/kickoff/search-tab-top-right.png diff --git a/kicker/data/kickoff/tab-bottom-left-topdown.png b/kicker/data/kickoff/tab-bottom-left-topdown.png Binary files differnew file mode 100644 index 000000000..a96a7bf12 --- /dev/null +++ b/kicker/data/kickoff/tab-bottom-left-topdown.png diff --git a/kicker/data/kickoff/tab-bottom-left.png b/kicker/data/kickoff/tab-bottom-left.png Binary files differnew file mode 100644 index 000000000..fd8a34aca --- /dev/null +++ b/kicker/data/kickoff/tab-bottom-left.png diff --git a/kicker/data/kickoff/tab-bottom-right-topdown.png b/kicker/data/kickoff/tab-bottom-right-topdown.png Binary files differnew file mode 100644 index 000000000..d1d80a6b3 --- /dev/null +++ b/kicker/data/kickoff/tab-bottom-right-topdown.png diff --git a/kicker/data/kickoff/tab-bottom-right.png b/kicker/data/kickoff/tab-bottom-right.png Binary files differnew file mode 100644 index 000000000..86d226b51 --- /dev/null +++ b/kicker/data/kickoff/tab-bottom-right.png diff --git a/kicker/data/kickoff/tab-center-topdown.png b/kicker/data/kickoff/tab-center-topdown.png Binary files differnew file mode 100644 index 000000000..c35438d91 --- /dev/null +++ b/kicker/data/kickoff/tab-center-topdown.png diff --git a/kicker/data/kickoff/tab-center.png b/kicker/data/kickoff/tab-center.png Binary files differnew file mode 100644 index 000000000..0ef1f6d34 --- /dev/null +++ b/kicker/data/kickoff/tab-center.png diff --git a/kicker/data/kickoff/tab-left_center.png b/kicker/data/kickoff/tab-left_center.png Binary files differnew file mode 100644 index 000000000..4c8c39794 --- /dev/null +++ b/kicker/data/kickoff/tab-left_center.png diff --git a/kicker/data/kickoff/tab-right_center.png b/kicker/data/kickoff/tab-right_center.png Binary files differnew file mode 100644 index 000000000..3df6564f4 --- /dev/null +++ b/kicker/data/kickoff/tab-right_center.png diff --git a/kicker/data/kickoff/tab-top-left-topdown.png b/kicker/data/kickoff/tab-top-left-topdown.png Binary files differnew file mode 100644 index 000000000..3df580e1d --- /dev/null +++ b/kicker/data/kickoff/tab-top-left-topdown.png diff --git a/kicker/data/kickoff/tab-top-left.png b/kicker/data/kickoff/tab-top-left.png Binary files differnew file mode 100644 index 000000000..910967a18 --- /dev/null +++ b/kicker/data/kickoff/tab-top-left.png diff --git a/kicker/data/kickoff/tab-top-right-topdown.png b/kicker/data/kickoff/tab-top-right-topdown.png Binary files differnew file mode 100644 index 000000000..dd672cad9 --- /dev/null +++ b/kicker/data/kickoff/tab-top-right-topdown.png diff --git a/kicker/data/kickoff/tab-top-right.png b/kicker/data/kickoff/tab-top-right.png Binary files differnew file mode 100644 index 000000000..e96019d6d --- /dev/null +++ b/kicker/data/kickoff/tab-top-right.png diff --git a/kicker/kicker/ui/browser_mnu.cpp b/kicker/kicker/ui/browser_mnu.cpp index 6802e6388..88ce30713 100644 --- a/kicker/kicker/ui/browser_mnu.cpp +++ b/kicker/kicker/ui/browser_mnu.cpp @@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <kfileitem.h> #include <kglobal.h> #include <kglobalsettings.h> +#include <kconfig.h> #include <kiconloader.h> #include <kio/global.h> #include <klocale.h> @@ -148,12 +149,14 @@ void PanelBrowserMenu::initialize() // only the first part menu got them if(_startid == 0 && !_filesOnly) { insertTitle(path()); + KConfig *c = KGlobal::config(); + c->setGroup("menus"); insertItem(CICON("kfm"), i18n("Open in File Manager"), this, TQT_SLOT(slotOpenFileManager())); - if (kapp->authorize("shell_access")) - insertItem(CICON("terminal"), i18n("Open in Terminal"), this, TQT_SLOT(slotOpenTerminal())); + if (kapp->authorize("shell_access") && c->readBoolEntry("kickerOpenInTerminalIsVisible",false)) + insertItem(CICON("terminal"), i18n("Open in Terminal"), this, TQT_SLOT(slotOpenTerminal())); + insertSeparator(); } - bool first_entry = true; bool dirfile_separator = false; unsigned int item_count = 0; diff --git a/kicker/kicker/ui/service_mnu.cpp b/kicker/kicker/ui/service_mnu.cpp index fa18a7038..3042eddfe 100644 --- a/kicker/kicker/ui/service_mnu.cpp +++ b/kicker/kicker/ui/service_mnu.cpp @@ -114,6 +114,11 @@ void PanelServiceMenu::fillMenu(KServiceGroup::Ptr& _root, TQStringList suppressGenericNames = _root->suppressGenericNames(); KServiceGroup::List::ConstIterator it = _list.begin(); + KSortableValueList<KSharedPtr<KSycocaEntry>,TQCString> slist; + KSortableValueList<KSharedPtr<KSycocaEntry>,TQCString> glist; + TQMap<TQString,TQString> specialTitle; + TQMap<TQString,TQString> categoryIcon; + bool separatorNeeded = false; for (; it != _list.end(); ++it) { @@ -121,19 +126,108 @@ void PanelServiceMenu::fillMenu(KServiceGroup::Ptr& _root, if (e->isType(KST_KServiceGroup)) { + KServiceGroup::Ptr g(static_cast<KServiceGroup *>(e)); + if ( KickerSettings::reduceMenuDepth() && g->SuSEshortMenu() ){ + KServiceGroup::List l = g->entries(true, excludeNoDisplay_ ); + if ( l.count() == 1 ) { + // the special case, we want to short the menu. + // TOFIX? : this works only for one level + KServiceGroup::List::ConstIterator _it=l.begin(); + KSycocaEntry *_e = *_it; + if (_e->isType(KST_KService)) { + KService::Ptr s(static_cast<KService *>(_e)); + TQString key; + if ( g->SuSEgeneralDescription() ) { + // we use the application name + key = s->name(); + if( !s->genericName().isEmpty()) { + if (KickerSettings::menuEntryFormat() == KickerSettings::NameAndDescription) + key = s->name() + " (" + s->genericName() + ")"; + else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName) + key = s->genericName() + " (" + s->name() + ")"; + else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly) + key = s->genericName(); + } + } + else { + // we use the normal menu description + key = s->name(); + if( !s->genericName().isEmpty()) { + if (KickerSettings::menuEntryFormat() == KickerSettings::NameAndDescription) + key = s->name() + " (" + g->caption() + ")"; + else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName) + key = g->caption() + " (" + s->name() + ")"; + else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly) + key = g->caption(); + } + } + specialTitle.insert( _e->name(), key ); + categoryIcon.insert( _e->name(), g->icon() ); + slist.insert( key.local8Bit(), _e ); + // and escape from here + continue; + } + } + } + glist.insert( g->caption().local8Bit(), e ); + }else if( e->isType(KST_KService)) { + KService::Ptr s(static_cast<KService *>(e)); + TQString name = s->name(); + if( !s->genericName().isEmpty()) { + if (KickerSettings::menuEntryFormat() == KickerSettings::NameAndDescription) + name = s->name() + " (" + s->genericName() + ")"; + else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName) + name = s->genericName() + " (" + s->name() + ")"; + else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly) + name = s->genericName(); + } + slist.insert( name.local8Bit(), e ); + } else + slist.insert( e->name().local8Bit(), e ); + } + + _list = _root->SuSEsortEntries( slist, glist, excludeNoDisplay_, true ); + it = _list.begin(); + + for (; it != _list.end(); ++it) { + KSycocaEntry * e = *it; + + if (e->isType(KST_KServiceGroup)) { KServiceGroup::Ptr g(static_cast<KServiceGroup *>(e)); + if ( KickerSettings::reduceMenuDepth() && g->SuSEshortMenu() ){ + KServiceGroup::List l = g->entries(true, excludeNoDisplay_ ); + if ( l.count() == 1 ) { + /* // the special case, we want to short the menu. + // TOFIX? : this works only for one level + KServiceGroup::List::ConstIterator _it=l.begin(); + KSycocaEntry *_e = *_it; + if (_e->isType(KST_KService)) { + KService::Ptr s(static_cast<KService *>(_e)); + if ( g->SuSEgeneralDescription() ) + // we use the application name + insertMenuItem(s, id++, -1, 0, TQString::null, TQString::null, g->icon() ); + else + // we use the normal menu description + insertMenuItem(s, id++, -1, 0, TQString::null, g->caption(), g->icon() ); + // and escape from here */ + continue; + // } + } + } + // standard sub menu + TQString groupCaption = g->caption(); - + // Avoid adding empty groups. KServiceGroup::Ptr subMenuRoot = KServiceGroup::group(g->relPath()); - + int nbChildCount = subMenuRoot->childCount(); if (nbChildCount == 0 && !g->showEmptyMenu()) - { + { continue; - } - + } + TQString inlineHeaderName = g->showInlineHeader() ? groupCaption : ""; // Item names may contain ampersands. To avoid them being converted // to accelerators, replace them with two ampersands. @@ -156,7 +250,8 @@ void PanelServiceMenu::fillMenu(KServiceGroup::Ptr& _root, } KService::Ptr s(static_cast<KService *>(e1)); - insertMenuItem(s, id++, -1, &suppressGenericNames); +// insertMenuItem(s, id++, -1, &suppressGenericNames); + insertMenuItem(s, id++, -1, &suppressGenericNames, TQString::null, specialTitle[s->name()], categoryIcon[s->name()] ); continue; } } @@ -222,7 +317,8 @@ void PanelServiceMenu::fillMenu(KServiceGroup::Ptr& _root, KService::Ptr s(static_cast<KService *>(e)); searchMenuItems.insert(id); - insertMenuItem(s, id++, -1, &suppressGenericNames); +// insertMenuItem(s, id++, -1, &suppressGenericNames); + insertMenuItem(s, id++, -1, &suppressGenericNames, TQString::null, specialTitle[s->name()], categoryIcon[s->name()] ); } else if (e->isType(KST_KServiceSeparator)) { @@ -304,7 +400,8 @@ void PanelServiceMenu::configChanged() void PanelServiceMenu::insertMenuItem(KService::Ptr & s, int nId, int nIndex/*= -1*/, const TQStringList *suppressGenericNames /* = 0 */, - const TQString & aliasname) + const TQString & aliasname, const TQString & label /*=TQString::NULL*/, + const TQString & categoryIcon /*=TQString::null*/) { TQString serviceName = (aliasname.isEmpty() ? s->name() : aliasname).simplifyWhiteSpace(); TQString comment = s->genericName().simplifyWhiteSpace(); @@ -355,7 +452,15 @@ void PanelServiceMenu::insertMenuItem(KService::Ptr & s, int nId, // to accelerators, replace them with two ampersands. serviceName.replace("&", "&&"); - int newId = insertItem(KickerLib::menuIconSet(s->icon()), serviceName, nId, nIndex); + TQString icon = s->icon(); + if (icon=="unknown") + icon = categoryIcon; + + int newId; + if ( label.isEmpty() ) + newId = insertItem(KickerLib::menuIconSet(s->icon()), serviceName, nId, nIndex); + else + newId = insertItem(KickerLib::menuIconSet(s->icon()), label, nId, nIndex); entryMap_.insert(newId, static_cast<KSycocaEntry*>(s)); } diff --git a/kicker/kicker/ui/service_mnu.h b/kicker/kicker/ui/service_mnu.h index 193e4faf8..44e35a6c2 100644 --- a/kicker/kicker/ui/service_mnu.h +++ b/kicker/kicker/ui/service_mnu.h @@ -89,7 +89,8 @@ protected slots: protected: void insertMenuItem(KService::Ptr & s, int nId, int nIndex = -1, const TQStringList *suppressGenericNames=0, - const TQString &aliasname = TQString::null); + const TQString &aliasname = TQString::null, + const TQString &label = TQString::null, const TQString &categoryIcon = TQString::null); virtual PanelServiceMenu * newSubMenu(const TQString & label, const TQString & relPath, TQWidget * parent, const char * name, diff --git a/kicker/libkicker/kickerSettings.kcfg b/kicker/libkicker/kickerSettings.kcfg index ff86c8431..6f7f2427e 100644 --- a/kicker/libkicker/kickerSettings.kcfg +++ b/kicker/libkicker/kickerSettings.kcfg @@ -126,6 +126,11 @@ <default>true</default> </entry> +<entry name="ReduceMenuDepth" type="Bool" > + <label>Simplify menus with only a single item inside</label> + <default>false</default> + </entry> + <entry name="MenuEntryHeight" type="Int" > <label>Height of menu entries in pixels</label> <default>0</default> diff --git a/kioslave/media/mediaimpl.cpp b/kioslave/media/mediaimpl.cpp index fb9e01480..b55b37e5d 100644 --- a/kioslave/media/mediaimpl.cpp +++ b/kioslave/media/mediaimpl.cpp @@ -281,6 +281,13 @@ bool MediaImpl::ensureMediumMounted(Medium &medium) return m_lastErrorCode==0; } + if (medium.id().isEmpty()) + { + m_lastErrorCode = KIO::ERR_COULD_NOT_MOUNT; + m_lastErrorMessage = i18n("No such medium."); + return false; + } + return true; } diff --git a/kioslave/media/mediamanager/halbackend.cpp b/kioslave/media/mediamanager/halbackend.cpp index b6763ee84..7b56d46ad 100644 --- a/kioslave/media/mediamanager/halbackend.cpp +++ b/kioslave/media/mediamanager/halbackend.cpp @@ -35,6 +35,7 @@ #include <kmountpoint.h> #include <kmessagebox.h> #include <kio/job.h> +#include <kprotocolinfo.h> #include <kstandarddirs.h> #include <kprocess.h> @@ -623,6 +624,13 @@ void HALBackend::setVolumeProperties(Medium* medium) case LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER: { medium->setIconName("ipod" + MOUNT_ICON_SUFFIX); + + if (libhal_device_get_property_QString(m_halContext, driveUdi.latin1(), "info.product") == "iPod" && + KProtocolInfo::isKnownProtocol( TQString("ipod") ) ) + { + medium->unmountableState( "ipod:/" ); + medium->mountableState( libhal_volume_is_mounted(halVolume) ); + } break; } case LIBHAL_DRIVE_TYPE_CAMERA: diff --git a/kioslave/smb/kio_smb_auth.cpp b/kioslave/smb/kio_smb_auth.cpp index d216e1e5b..d4a48239f 100644 --- a/kioslave/smb/kio_smb_auth.cpp +++ b/kioslave/smb/kio_smb_auth.cpp @@ -144,6 +144,7 @@ bool SMBSlave::checkPassword(SMBUrl &url) if ( openPassDlg(info) ) { kdDebug(KIO_SMB) << "openPassDlg returned " << info.username << endl; url.setUser(info.username); + url.setPass(info.password); return true; } kdDebug(KIO_SMB) << "no value from openPassDlg\n"; diff --git a/kioslave/system/entries/documents.desktop b/kioslave/system/entries/documents.desktop index 16016e0c5..a2c0fe528 100644 --- a/kioslave/system/entries/documents.desktop +++ b/kioslave/system/entries/documents.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Type=Link Path[$e]=$( kio_system_documenthelper ) -Icon=folder_important +Icon=folder_man Name=Documents Folder Name[af]=Dokument Gids Name[ar]=مستنداتي diff --git a/klipper/klipperrc.desktop b/klipper/klipperrc.desktop index ba04cf594..5ad72c141 100644 --- a/klipper/klipperrc.desktop +++ b/klipper/klipperrc.desktop @@ -232,7 +232,7 @@ Number of commands=5 Regexp=^https?://. [Action_1/Command_0] -Commandline=kfmclient exec %s +Commandline=kfmclient openURL %s Description=Open with &Konqueror Description[af]=Maak oop met Konqueror Description[ar]=إفتح بــ &Konqueror @@ -1644,7 +1644,7 @@ Number of commands=5 Regexp=^ftp://. [Action_6/Command_0] -Commandline=kfmclient exec %s +Commandline=kfmclient openURL %s Description=Open with &Konqueror Description[af]=Maak oop met Konqueror Description[ar]=إفتح بــ &Konqueror diff --git a/konqueror/Makefile.am b/konqueror/Makefile.am index 0fd86b2f5..116a7a915 100644 --- a/konqueror/Makefile.am +++ b/konqueror/Makefile.am @@ -48,8 +48,8 @@ noinst_HEADERS = KonqMainWindowIface.h KonqViewIface.h delayedinitializer.h \ konq_misc.h konq_openurlrequest.h konq_profiledlg.h konq_run.h \ konq_view.h konq_viewmgr.h konq_extensionmanager.h version.h -konqueror_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -konqueror_la_LIBADD = ../libkonq/libkonq.la libkonqueror_intern.la $(LIBMALLOC) $(LIB_KUTILS) +konqueror_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -lconnectionmanager +konqueror_la_LIBADD = ../libkonq/libkonq.la libkonqueror_intern.la $(LIBMALLOC) $(LIB_KUTILS) -lconnectionmanager # Hmm, this experiment of a static konq failed, don't trust it... # (but feel free to fix it :) diff --git a/konqueror/konq_combo.cc b/konqueror/konq_combo.cc index 86747ebde..0a73e6c83 100644 --- a/konqueror/konq_combo.cc +++ b/konqueror/konq_combo.cc @@ -128,6 +128,9 @@ KonqCombo::KonqCombo( TQWidget *parent, const char *name ) connect( this, TQT_SIGNAL(activated( const TQString& )), TQT_SLOT(slotActivated( const TQString& )) ); + setHistoryEditorEnabled( true ); + connect( this, TQT_SIGNAL(removed( const TQString&) ), TQT_SLOT(slotRemoved( const TQString& )) ); + if ( !kapp->dcopClient()->isAttached() ) kapp->dcopClient()->attach(); } @@ -507,6 +510,15 @@ void KonqCombo::slotCleared() kapp->dcopClient()->send( "konqueror*", "KonquerorIface", "comboCleared(TQCString)", data); } +void KonqCombo::slotRemoved( const TQString& item ) +{ + TQByteArray data; + TQDataStream s( data, IO_WriteOnly ); + s << item << kapp->dcopClient()->defaultObject(); + kapp->dcopClient()->send( "konqueror*", "KonquerorIface", + "removeFromCombo(TQString,TQCString)", data); +} + void KonqCombo::removeURL( const TQString& url ) { setUpdatesEnabled( false ); diff --git a/konqueror/konq_combo.h b/konqueror/konq_combo.h index dfb2778dc..3650eb9a4 100644 --- a/konqueror/konq_combo.h +++ b/konqueror/konq_combo.h @@ -87,6 +87,7 @@ signals: private slots: void slotCleared(); + void slotRemoved( const TQString& item ); void slotSetIcon( int index ); void slotActivated( const TQString& text ); diff --git a/konqueror/konq_frame.cc b/konqueror/konq_frame.cc index 77310ebbc..149a2f92d 100644 --- a/konqueror/konq_frame.cc +++ b/konqueror/konq_frame.cc @@ -34,6 +34,7 @@ #include <kprogress.h> #include <klocale.h> #include <ksqueezedtextlabel.h> +#include <networkstatusindicator.h> #include "konq_events.h" #include "konq_frame.h" @@ -97,6 +98,10 @@ KonqFrameStatusBar::KonqFrameStatusBar( KonqFrame *_parent, const char *_name ) m_progressBar->hide(); addWidget( m_progressBar, 0, true /*permanent->right align*/ ); + StatusBarNetworkStatusIndicator * indicator = new StatusBarNetworkStatusIndicator( this, "networkstatusindicator" ); + addWidget( indicator, 0, false ); + indicator->init(); + fontChange(TQFont()); installEventFilter( this ); } diff --git a/konsole/other/x11r5.keytab b/konsole/other/x11r5.keytab index 75ba06ec4..c731807ca 100644 --- a/konsole/other/x11r5.keytab +++ b/konsole/other/x11r5.keytab @@ -32,10 +32,10 @@ key Left -Shift : "\EOD" key Enter : "\r" -key Home : "\E[1~" +key Home : "\E[H" key Insert-Shift : "\E[2~" key Delete : "\E[3~" -key End : "\E[4~" +key End : "\E[F" key Prior -Shift : "\E[5~" key Next -Shift : "\E[6~" diff --git a/kscreensaver/Makefile.am b/kscreensaver/Makefile.am index 75cf37640..2823d4e17 100644 --- a/kscreensaver/Makefile.am +++ b/kscreensaver/Makefile.am @@ -3,13 +3,13 @@ AM_CPPFLAGS = -UQT_NO_ASCII_CAST -INCLUDES = $(all_includes) +INCLUDES = $(GLINC) $(all_includes) AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) bin_PROGRAMS = krandom.kss kblankscrn.kss krandom_kss_SOURCES = random.cpp -krandom_kss_LDADD = $(LIB_KDEUI) -lm +krandom_kss_LDADD = $(LIB_KDEUI) $(GLLIB) -lm kblankscrn_kss_SOURCES = blankscrn.cpp kblankscrn_kss_LDADD = $(LIB_KDEUI) -lkscreensaver -lm diff --git a/kscreensaver/random.cpp b/kscreensaver/random.cpp index c1cd8dcad..cd984a145 100644 --- a/kscreensaver/random.cpp +++ b/kscreensaver/random.cpp @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- // // Screen savers for KDE // @@ -19,6 +19,7 @@ #include <tqframe.h> #include <tqcheckbox.h> #include <tqwidget.h> +#include <tqfileinfo.h> #include <kapplication.h> #include <kstandarddirs.h> @@ -36,7 +37,7 @@ #define MAX_ARGS 20 -void usage(char *name) +static void usage(char *name) { puts(i18n("Usage: %1 [-setup] [args]\n" "Starts a random screen saver.\n" @@ -60,6 +61,43 @@ static const KCmdLineOptions options[] = //---------------------------------------------------------------------------- +#ifdef HAVE_GLXCHOOSEVISUAL +#include <GL/glx.h> +#endif + +//------------------------------------- +bool hasDirectRendering () { + Display *dpy = TQApplication::desktop()->x11Display(); + +#ifdef HAVE_GLXCHOOSEVISUAL + int attribSingle[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + None + }; + XVisualInfo* visinfo = glXChooseVisual ( + dpy, TQApplication::desktop()->primaryScreen(), attribSingle + ); + if (visinfo) { + GLXContext ctx = glXCreateContext ( dpy, visinfo, NULL, True ); + if (glXIsDirect(dpy, ctx)) { + glXDestroyContext (dpy,ctx); + return true; + } + glXDestroyContext (dpy,ctx); + return false; + } else { + return false; + } +#else +#error no GL? + return false; +#endif + +} + int main(int argc, char *argv[]) { KLocale::setMainCatalogue("kscreensaver"); @@ -103,55 +141,63 @@ int main(int argc, char *argv[]) KConfig type("krandom.kssrc"); type.setGroup("Settings"); - bool opengl = type.readBoolEntry("OpenGL"); + bool opengl = type.readBoolEntry("OpenGL", hasDirectRendering()); + kdDebug() << "hasOPEN " << opengl << endl; bool manipulatescreen = type.readBoolEntry("ManipulateScreen"); bool fortune = !KStandardDirs::findExe("fortune").isEmpty(); + TQStringList defaults = type.readListEntry( "Defaults" ); + TQMap<TQString, int> def_numbers; + for ( TQStringList::ConstIterator it = defaults.begin(); it != defaults.end(); ++it ) { + int index = ( *it ).find( ':' ); + if ( index == -1 ) + def_numbers[*it] = 1; + else + def_numbers[( *it ).left( index )] = ( *it ).mid( index + 1 ).toInt(); + } for (uint i = 0; i < tempSaverFileList.count(); i++) { - kdDebug() << "Looking at " << tempSaverFileList[i] << endl; + int howoften = 1; + if ( defaults.count() != 0 ) { + TQFileInfo fi( tempSaverFileList[i] ); + if ( def_numbers.contains( fi.fileName() ) ) + howoften = def_numbers[fi.fileName()]; + else + howoften = 0; + } + KDesktopFile saver(tempSaverFileList[i], true); - if(!saver.tryExec()) - continue; - kdDebug() << "read X-KDE-Type" << endl; + if (!saver.tryExec()) + continue; TQString saverType = saver.readEntry("X-KDE-Type"); - - if (saverType.isEmpty()) // no X-KDE-Type defined so must be OK - { - saverFileList.append(tempSaverFileList[i]); - } - else - { + if (!saverType.isEmpty()) // no X-KDE-Type defined so must be OK + { TQStringList saverTypes = TQStringList::split(";", saverType); for (TQStringList::ConstIterator it = saverTypes.begin(); it != saverTypes.end(); ++it ) { - kdDebug() << "saverTypes is "<< *it << endl; if (*it == "ManipulateScreen") { - if (manipulatescreen) - { - saverFileList.append(tempSaverFileList[i]); - } + if (!manipulatescreen) + howoften = 0; } else if (*it == "OpenGL") { - if (opengl) - { - saverFileList.append(tempSaverFileList[i]); - } + if (!opengl) + howoften = 0; } if (*it == "Fortune") { - if (fortune) - { - saverFileList.append(tempSaverFileList[i]); - } + if (!fortune) + howoften = 0; } } } + for ( int j = 0; j < howoften; ++j ) + saverFileList.append(tempSaverFileList[i]); } + kdDebug() << "final " << saverFileList << endl; KRandomSequence rnd; int indx = rnd.getLong(saverFileList.count()); @@ -229,7 +275,7 @@ KRandomSetup::KRandomSetup( TQWidget *parent, const char *name ) KConfig config("krandom.kssrc"); config.setGroup("Settings"); - openGL->setChecked(config.readBoolEntry("OpenGL", true)); + openGL->setChecked(config.readBoolEntry("OpenGL", hasDirectRendering())); manipulateScreen->setChecked(config.readBoolEntry("ManipulateScreen", true)); } diff --git a/ksmserver/KSMServerInterface.h b/ksmserver/KSMServerInterface.h index 52fdf0942..a628b92ba 100644 --- a/ksmserver/KSMServerInterface.h +++ b/ksmserver/KSMServerInterface.h @@ -22,6 +22,8 @@ k_dcop: virtual void suspendStartup( TQCString ) = 0; virtual void resumeStartup( TQCString ) = 0; + + virtual void logoutTimed( int, int, TQString ) = 0; }; #endif diff --git a/ksmserver/Makefile.am b/ksmserver/Makefile.am index 62f9d8976..19b328bc5 100644 --- a/ksmserver/Makefile.am +++ b/ksmserver/Makefile.am @@ -28,7 +28,7 @@ ksmserver_la_METASOURCES = AUTO # Order is important for --enable-final! ksmserver_la_SOURCES = main.cpp server.cpp shutdowndlg.cpp \ legacy.cpp startup.cpp shutdown.cpp client.cpp \ - KSMServerInterface.skel server.skel + KSMServerInterface.skel server.skel timed.ui ksmserver_la_LDFLAGS = $(all_libraries) -avoid-version -module ksmserver_la_LIBADD = ../kdmlib/libdmctl.la $(LIB_KDEUI) $(HAL_LIBS) $(DBUS_LIBS) @@ -42,7 +42,7 @@ updatedir = $(kde_datadir)/kconf_update EXTRA_PROGRAMS = testsh -testsh_SOURCES = test.cpp +testsh_SOURCES = test.cpp timed.ui testsh_LDFLAGS = $(all_libraries) $(KDE_RPATH) testsh_LDADD = $(LIB_KDEUI) shutdowndlg.lo ../kdmlib/libdmctl.la $(HAL_LIBS) $(DBUS_LIBS) diff --git a/ksmserver/server.h b/ksmserver/server.h index 3d5904e53..0fc900042 100644 --- a/ksmserver/server.h +++ b/ksmserver/server.h @@ -85,6 +85,7 @@ public: // public API void restoreSession( TQString sessionName ); void startDefaultSession(); + void shutdown( KApplication::ShutdownConfirm confirm, KApplication::ShutdownType sdtype, KApplication::ShutdownMode sdmode ); @@ -92,6 +93,11 @@ public: virtual void suspendStartup( TQCString app ); virtual void resumeStartup( TQCString app ); + bool checkStatus( bool &logoutConfirmed, bool &maysd, + KApplication::ShutdownConfirm confirm, + KApplication::ShutdownType sdtype, + KApplication::ShutdownMode sdmode ); + public slots: void cleanUp(); @@ -142,6 +148,11 @@ private: bool defaultSession() const; // empty session void setupXIOErrorHandler(); + void shutdownInternal( KApplication::ShutdownConfirm confirm, + KApplication::ShutdownType sdtype, + KApplication::ShutdownMode sdmode, + TQString bootOption = TQString::null ); + void performLegacySessionSave(); void storeLegacySession( KConfig* config ); void restoreLegacySession( KConfig* config ); @@ -157,6 +168,7 @@ private: // public dcop interface void logout( int, int, int ); + virtual void logoutTimed( int, int, TQString ); TQStringList sessionList(); TQString currentSession(); void saveCurrentSession(); diff --git a/ksmserver/shutdown.cpp b/ksmserver/shutdown.cpp index 16fab8b4d..a850d40be 100644 --- a/ksmserver/shutdown.cpp +++ b/ksmserver/shutdown.cpp @@ -93,14 +93,16 @@ void KSMServer::logout( int confirm, int sdtype, int sdmode ) (KApplication::ShutdownMode)sdmode ); } -void KSMServer::shutdown( KApplication::ShutdownConfirm confirm, - KApplication::ShutdownType sdtype, KApplication::ShutdownMode sdmode ) +bool KSMServer::checkStatus( bool &logoutConfirmed, bool &maysd, + KApplication::ShutdownConfirm confirm, + KApplication::ShutdownType sdtype, + KApplication::ShutdownMode sdmode ) { pendingShutdown.stop(); if( dialogActive ) - return; + return false; if( state >= Shutdown ) // already performing shutdown - return; + return false; if( state != Idle ) // performing startup { // perform shutdown as soon as startup is finished, in order to avoid saving partial session @@ -111,25 +113,44 @@ void KSMServer::shutdown( KApplication::ShutdownConfirm confirm, pendingShutdown_sdtype = sdtype; pendingShutdown_sdmode = sdmode; } - return; + return false; } KConfig *config = KGlobal::config(); config->reparseConfiguration(); // config may have changed in the KControl module config->setGroup("General" ); - bool logoutConfirmed = + logoutConfirmed = (confirm == KApplication::ShutdownConfirmYes) ? false : - (confirm == KApplication::ShutdownConfirmNo) ? true : - !config->readBoolEntry( "confirmLogout", true ); - bool maysd = false; + (confirm == KApplication::ShutdownConfirmNo) ? true : + !config->readBoolEntry( "confirmLogout", true ); + maysd = false; if (config->readBoolEntry( "offerShutdown", true ) && DM().canShutdown()) maysd = true; if (!maysd) { if (sdtype != KApplication::ShutdownTypeNone && sdtype != KApplication::ShutdownTypeDefault && logoutConfirmed) - return; /* unsupported fast shutdown */ + return false; /* unsupported fast shutdown */ + } + + return true; +} + +void KSMServer::shutdownInternal( KApplication::ShutdownConfirm confirm, + KApplication::ShutdownType sdtype, + KApplication::ShutdownMode sdmode, + TQString bopt ) +{ + bool maysd = false; + bool logoutConfirmed = false; + if ( !checkStatus( logoutConfirmed, maysd, confirm, sdtype, sdmode ) ) + return; + + KConfig *config = KGlobal::config(); + + config->setGroup("General" ); + if (!maysd) { sdtype = KApplication::ShutdownTypeNone; } else if (sdtype == KApplication::ShutdownTypeDefault) sdtype = (KApplication::ShutdownType) @@ -138,7 +159,6 @@ void KSMServer::shutdown( KApplication::ShutdownConfirm confirm, sdmode = KApplication::ShutdownModeInteractive; dialogActive = true; - TQString bopt; if ( !logoutConfirmed ) { KSMShutdownFeedback::start(); // make the screen gray logoutConfirmed = @@ -204,6 +224,42 @@ void KSMServer::shutdown( KApplication::ShutdownConfirm confirm, dialogActive = false; } +void KSMServer::shutdown( KApplication::ShutdownConfirm confirm, + KApplication::ShutdownType sdtype, KApplication::ShutdownMode sdmode ) +{ + shutdownInternal( confirm, sdtype, sdmode ); +} + +#include <kmessagebox.h> + +void KSMServer::logoutTimed( int sdtype, int sdmode, TQString bootOption ) +{ + int confirmDelay; + + KConfig* config = KGlobal::config(); + config->setGroup( "General" ); + + if ( sdtype == KApplication::ShutdownTypeHalt ) + confirmDelay = config->readNumEntry( "confirmShutdownDelay", 31 ); + else if ( sdtype == KApplication::ShutdownTypeReboot ) + confirmDelay = config->readNumEntry( "confirmRebootDelay", 31 ); + else + confirmDelay = config->readNumEntry( "confirmLogoutDelay", 31 ); + + bool result = true; + if (confirmDelay) { + KSMShutdownFeedback::start(); // make the screen gray + result = KSMDelayedMessageBox::showTicker( (KApplication::ShutdownType)sdtype, bootOption, confirmDelay ); + KSMShutdownFeedback::stop(); // make the screen become normal again + } + + if ( result ) + shutdownInternal( KApplication::ShutdownConfirmNo, + (KApplication::ShutdownType)sdtype, + (KApplication::ShutdownMode)sdmode, + bootOption ); +} + void KSMServer::pendingShutdownTimeout() { shutdown( pendingShutdown_confirm, pendingShutdown_sdtype, pendingShutdown_sdmode ); diff --git a/ksmserver/shutdowndlg.cpp b/ksmserver/shutdowndlg.cpp index 7b0493559..f6295a158 100644 --- a/ksmserver/shutdowndlg.cpp +++ b/ksmserver/shutdowndlg.cpp @@ -29,6 +29,7 @@ Copyright (C) 2000 Matthias Ettrich <[email protected]> #include <tqregexp.h> #include <klocale.h> +#include <kconfig.h> #include <kapplication.h> #include <kdebug.h> #include <kpushbutton.h> @@ -340,6 +341,7 @@ KSMShutdownDlg::KSMShutdownDlg( TQWidget* parent, buttonlay->addStretch( 1 ); // End session KPushButton* btnLogout = new KPushButton( KGuiItem( i18n("&End Current Session"), "undo"), frame ); + TQToolTip::add( btnLogout, i18n( "<qt><h3>End Current Session</h3><p>Log out of the current session to login with a different user</p></qt>" ) ); btnFont = btnLogout->font(); buttonlay->addWidget( btnLogout ); connect(btnLogout, TQT_SIGNAL(clicked()), TQT_SLOT(slotLogout())); @@ -510,14 +512,16 @@ KSMShutdownDlg::KSMShutdownDlg( TQWidget* parent, { // Shutdown KPushButton* btnHalt = new KPushButton( KGuiItem( i18n("&Turn Off Computer"), "exit"), frame ); + TQToolTip::add( btnHalt, i18n( "<qt><h3>Turn Off Computer</h3><p>Log out of the current session and turn off the computer</p></qt>" ) ); btnHalt->setFont( btnFont ); buttonlay->addWidget( btnHalt ); connect(btnHalt, TQT_SIGNAL(clicked()), TQT_SLOT(slotHalt())); - if ( sdtype == KApplication::ShutdownTypeHalt ) + if ( sdtype == KApplication::ShutdownTypeHalt || getenv("KDM_AUTOLOGIN") ) btnHalt->setFocus(); // Reboot KSMDelayedPushButton* btnReboot = new KSMDelayedPushButton( KGuiItem( i18n("&Restart Computer"), "reload"), frame ); + TQToolTip::add( btnReboot, i18n( "<qt><h3>Restart Computer</h3><p>Log out of the current session and restart the computer</p><p>Hold the mouse button or the space bar for a short while to get a list of options what to boot</p></qt>" ) ); btnReboot->setFont( btnFont ); buttonlay->addWidget( btnReboot ); @@ -761,6 +765,70 @@ void KSMDelayedPushButton::slotTimeout() setDown(false); } +KSMDelayedMessageBox::KSMDelayedMessageBox( KApplication::ShutdownType sdtype, const TQString &bootOption, int confirmDelay ) + : TimedLogoutDlg( 0, 0, true, WType_Popup ), m_remaining(confirmDelay) +{ + if ( sdtype == KApplication::ShutdownTypeHalt ) + { + m_title->setText( i18n( "Would you like to turn off your computer?" ) ); + m_template = i18n( "This computer will turn off automatically\n" + "after %1 seconds." ); + m_logo->setPixmap( BarIcon( "exit", 48 ) ); + } else if ( sdtype == KApplication::ShutdownTypeReboot ) + { + if (bootOption.isEmpty()) + m_title->setText( i18n( "Would you like to reboot your computer?" ) ); + else + m_title->setText( i18n( "Would you like to reboot to \"%1\"?" ).arg(bootOption) ); + m_template = i18n( "This computer will reboot automatically\n" + "after %1 seconds." ); + m_logo->setPixmap( BarIcon( "reload", 48 ) ); + } else { + m_title->setText( i18n( "Would you like to end your current session?" ) ); + m_template = i18n( "This session will end\n" + "after %1 seconds automatically." ); + m_logo->setPixmap( BarIcon( "previous", 48 ) ); + } + + updateText(); + adjustSize(); + if ( double( height() ) / width() < 0.25 ) + { + setFixedHeight( qRound( width() * 0.3 ) ); + adjustSize(); + } + TQTimer *timer = new TQTimer( this ); + timer->start( 1000 ); + connect( timer, TQT_SIGNAL( timeout() ), TQT_SLOT( updateText() ) ); + KDialog::centerOnScreen(this); +} + +void KSMDelayedMessageBox::updateText() +{ + m_remaining--; + if ( m_remaining == 0 ) + { + accept(); + return; + } + m_text->setText( m_template.arg( m_remaining ) ); +} + +bool KSMDelayedMessageBox::showTicker( KApplication::ShutdownType sdtype, const TQString &bootOption, int confirmDelay ) +{ + kapp->enableStyles(); + KSMDelayedMessageBox msg( sdtype, bootOption, confirmDelay ); + TQSize sh = msg.sizeHint(); + TQRect rect = KGlobalSettings::desktopGeometry(TQCursor::pos()); + + msg.move(rect.x() + (rect.width() - sh.width())/2, + rect.y() + (rect.height() - sh.height())/2); + bool result = msg.exec(); + + kapp->disableStyles(); + return result; +} + KSMPushButton::KSMPushButton( const KGuiItem &item, TQWidget *parent, const char *name) diff --git a/ksmserver/shutdowndlg.h b/ksmserver/shutdowndlg.h index a1d720669..79ee8ca37 100644 --- a/ksmserver/shutdowndlg.h +++ b/ksmserver/shutdowndlg.h @@ -26,6 +26,7 @@ class TQString; class KAction; +#include "timed.h" #include <kapplication.h> #include <kpixmapio.h> @@ -165,4 +166,22 @@ class FlatButton : public QToolButton +class TQLabel; + +class KSMDelayedMessageBox : public TimedLogoutDlg +{ + Q_OBJECT + +public: + KSMDelayedMessageBox( KApplication::ShutdownType sdtype, const TQString &bootOption, int confirmDelay ); + static bool showTicker( KApplication::ShutdownType sdtype, const TQString &bootOption, int confirmDelay ); + +protected slots: + void updateText(); + +private: + TQString m_template; + int m_remaining; +}; + #endif diff --git a/ksmserver/test.cpp b/ksmserver/test.cpp index 846c449db..8f248725f 100644 --- a/ksmserver/test.cpp +++ b/ksmserver/test.cpp @@ -14,11 +14,16 @@ main(int argc, char *argv[]) a.iconLoader()->addAppDir("ksmserver"); KSMShutdownFeedback::start(); + // ShutdownTypeNone == Logout == 0 + // ShutdownTypeReboot == 1 + // ShutdownTypeHalt == 2 KApplication::ShutdownType sdtype = KApplication::ShutdownTypeNone; TQString bopt; + KSMDelayedMessageBox::showTicker( sdtype ); + /* (void)KSMShutdownDlg::confirmShutdown( true, sdtype, - bopt ); + bopt );*/ /* (void)KSMShutdownDlg::confirmShutdown( false, sdtype, bopt ); */ diff --git a/ksmserver/timed.ui b/ksmserver/timed.ui new file mode 100644 index 000000000..23d7aa2a0 --- /dev/null +++ b/ksmserver/timed.ui @@ -0,0 +1,352 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>TimedLogoutDlg</class> +<widget class="QDialog"> + <property name="name"> + <cstring>TimedLogoutDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>381</width> + <height>131</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>Confirmation</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QFrame"> + <property name="name"> + <cstring>frame3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <property name="lineWidth"> + <number>2</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="midLineWidth"> + <number>0</number> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout10</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <spacer> + <property name="name"> + <cstring>spacer3_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>MinimumExpanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>2</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>m_logo</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>48</width> + <height>48</height> + </size> + </property> + <property name="scaledContents"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>MinimumExpanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>2</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>7</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_title</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + <bold>1</bold> + </font> + </property> + <property name="text"> + <string>Would you like to shutdown your computer?</string> + </property> + <property name="textFormat"> + <enum>PlainText</enum> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignLeft</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>m_text</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>If you do not act, your computer will shutdown +after X automatically.</string> + </property> + <property name="textFormat"> + <enum>RichText</enum> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Preferred</enum> + </property> + <property name="sizeHint"> + <size> + <width>30</width> + <height>0</height> + </size> + </property> + </spacer> + </vbox> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>90</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>pushButton1</cstring> + </property> + <property name="text"> + <string>Confirm</string> + </property> + <property name="on"> + <bool>false</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>90</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>pushButton2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2_2_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>90</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>pushButton1</sender> + <signal>clicked()</signal> + <receiver>TimedLogoutDlg</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>pushButton2</sender> + <signal>clicked()</signal> + <receiver>TimedLogoutDlg</receiver> + <slot>reject()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kwin/workspace.cpp b/kwin/workspace.cpp index fe008c399..bc8914f5b 100644 --- a/kwin/workspace.cpp +++ b/kwin/workspace.cpp @@ -59,6 +59,17 @@ KSelectionOwner* kompmgr_selection; bool allowKompmgrRestart = TRUE; +bool supportsCompMgr() +{ + int i; + + bool damageExt = XQueryExtension(qt_xdisplay(), "DAMAGE", &i, &i, &i); + bool compositeExt = XQueryExtension(qt_xdisplay(), "Composite", &i, &i, &i); + bool xfixesExt = XQueryExtension(qt_xdisplay(), "XFIXES", &i, &i, &i); + + return damageExt && compositeExt && xfixesExt; +} + // Rikkus: This class is too complex. It needs splitting further. // It's a nightmare to understand, especially with so few comments :( @@ -200,6 +211,9 @@ Workspace::Workspace( bool restore ) connect( kapp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized())); #endif + if (!supportsCompMgr()) + options->useTranslucency = false; + // start kompmgr - i wanted to put this into main.cpp, but that would prevent dcop support, as long as Application was no dcop_object if (options->useTranslucency) { diff --git a/kxkb/kcmlayout.cpp b/kxkb/kcmlayout.cpp index 502bf7972..7af7ae691 100644 --- a/kxkb/kcmlayout.cpp +++ b/kxkb/kcmlayout.cpp @@ -352,6 +352,9 @@ void LayoutConfig::add() // Create a copy of the sel widget, as one might add the same layout more // than one time, with different variants. TQListViewItem* toadd = copyLVI(sel, widget->listLayoutsDst); + + // Turn on "Include Latin layout" for new language by default (bnc:204402) + toadd->setText(LAYOUT_COLUMN_INCLUDE, "us"); widget->listLayoutsDst->insertItem(toadd); if( widget->listLayoutsDst->childCount() > 1 ) diff --git a/nsplugins/nspluginloader.cpp b/nsplugins/nspluginloader.cpp index e9c502169..3824334c0 100644 --- a/nsplugins/nspluginloader.cpp +++ b/nsplugins/nspluginloader.cpp @@ -326,7 +326,7 @@ TQString NSPluginLoader::lookup(const TQString &mimeType) } -bool NSPluginLoader::loadViewer() +bool NSPluginLoader::loadViewer(const TQString &mimeType) { kdDebug() << "NSPluginLoader::loadViewer" << endl; @@ -350,7 +350,7 @@ bool NSPluginLoader::loadViewer() } // find the external artsdsp process - if( _useArtsdsp ) { + if( _useArtsdsp && mimeType != "application/pdf" ) { kdDebug() << "trying to use artsdsp" << endl; TQString artsdsp = KGlobal::dirs()->findExe("artsdsp"); if (!artsdsp) @@ -464,7 +464,7 @@ NSPluginInstance *NSPluginLoader::newInstance(TQWidget *parent, TQString url, if ( !_viewer ) { // load plugin viewer process - loadViewer(); + loadViewer(mimeType); if ( !_viewer ) { diff --git a/nsplugins/nspluginloader.h b/nsplugins/nspluginloader.h index 6c2fe83c0..1748bb504 100644 --- a/nsplugins/nspluginloader.h +++ b/nsplugins/nspluginloader.h @@ -101,7 +101,7 @@ protected: TQString lookup(const TQString &mimeType); TQString lookupMimeType(const TQString &url); - bool loadViewer(); + bool loadViewer(const TQString &mimeType); void unloadViewer(); protected slots: diff --git a/nsplugins/pluginscan.cpp b/nsplugins/pluginscan.cpp index 82a5defb2..6914deb93 100644 --- a/nsplugins/pluginscan.cpp +++ b/nsplugins/pluginscan.cpp @@ -470,7 +470,7 @@ void writeServicesFile( TQStringList mimeTypes ) ts << "Icon=netscape" << endl; ts << "Comment=" << i18n("Netscape plugin viewer") << endl; ts << "X-KDE-Library=libnsplugin" << endl; - ts << "InitialPreference=0" << endl; + ts << "InitialPreference=7" << endl; ts << "ServiceTypes=KParts/ReadOnlyPart,Browser/View" << endl; ts << "X-KDE-BrowserView-PluginsInfo=nsplugins/pluginsinfo" << endl; |