Logo Search packages:      
Sourcecode: basket version File versions  Download package

container.cpp

/***************************************************************************
 *   Copyright (C) 2003 by Sébastien Laoût                                 *
 *   sebastien.laout@tuxfamily.org                                         *
 *                                                                         *
 *   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 <qtabwidget.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qcursor.h>
#include <qwhatsthis.h>

#include <ksqueezedtextlabel.h>
#include <qpoint.h>
#include <qpixmap.h>
#include <qinputdialog.h>
#include <kpopupmenu.h>
#include <kiconloader.h>
#include <kiconeffect.h>
#include <qiconset.h>
#include <kaction.h>
#include <kapp.h>
#include <klocale.h>
#include <kmenubar.h>
#include <kedittoolbar.h>
#include <qsignalmapper.h>
#include <qstringlist.h>

#include <kstandarddirs.h>
#include <qdir.h>
#include <qstringlist.h>
#include <kmessagebox.h>
#include <kstatusbar.h>
#include <qtimer.h>
#include <qaction.h>
#include <kstdaccel.h>
#include <kglobalaccel.h>
#include <kkeydialog.h>
#include <kpassivepopup.h>
#include <kconfig.h>
#include <kcolordialog.h>

#include <kdeversion.h>
#include <qdesktopwidget.h>
#include <kwin.h>

#include "container.h"
#include "basket.h"
#include "basketproperties.h"
#include "item.h"
#include "onclickaction.h"
#include "clickcursorfeedback.h"
#include "settings.h"
#include "global.h"
#include "addbasketwizard.h"
#include "basketfactory.h"
#include "popupmenu.h"
#include "xmlwork.h"
#include "debugwindow.h"
#include "itemfactory.h"

/** DektopColorPicker */

/* From QT documentation:
 * " Note that only visible widgets can grab mouse input.
 *   If isVisible() returns FALSE for a widget, that widget cannot call grabMouse(). "
 * So, we should use an always visible widget to be able to pick a color from screen,
 * even by first hidding the main window (user seldomly want to grab a color from BasKet!)
 * or use a global shortcut (main window can be hidden when hitting that shortcut).
 */

00086 DesktopColorPicker::DesktopColorPicker()
 : QDesktopWidget()
{
      m_gettingColorFromScreen = false;
}

DesktopColorPicker::~DesktopColorPicker()
{
}

00096 void DesktopColorPicker::pickColor()
{
      m_gettingColorFromScreen = true;
//    Global::mainContainer->setActive(false);
      QTimer::singleShot( 50, this, SLOT(slotDelayedPick()) );
}

/* When firered from basket context menu, and not from menu, grabMouse doesn't work!
 * It's perhapse because context menu call slotColorFromScreen() and then
 * ungrab the mouse (since menus grab the mouse).
 * But why isn't there such bug with normal menus?...
 * By calling this method with a QTimer::singleShot, we are sure context menu code is
 * finished and we can grab the mouse without loosing the grab:
 */
void DesktopColorPicker::slotDelayedPick()
{
      grabKeyboard();
      grabMouse(crossCursor);
}

/* Validate the color
 */
void DesktopColorPicker::mouseReleaseEvent(QMouseEvent *event)
{
      if (m_gettingColorFromScreen) {
            m_gettingColorFromScreen = false;
            releaseMouse();
            releaseKeyboard();
            QColor color = KColorDialog::grabColor(event->globalPos());
            emit pickedColor(color);
//          ItemFactory::createItemColor(color, Global::mainContainer->currentBasket());
      } else
            QDesktopWidget::mouseReleaseEvent(event);
}

/* Cancel the mode
 */
void DesktopColorPicker::keyPressEvent(QKeyEvent *event)
{
      if (m_gettingColorFromScreen)
            if (event->key() == Qt::Key_Escape) {
                  m_gettingColorFromScreen = false;
                  releaseMouse();
                  releaseKeyboard();
                  emit canceledPick();
            }
      else
            QDesktopWidget::keyPressEvent(event);
}

/** KSystemTray2 */

// To draw the systray screenshot image:
#include <qdesktopwidget.h>
#include <qmime.h>
#include <qpainter.h>
#include <qpoint.h>
#include <qpixmap.h>
// To know the program name:
#include <kglobal.h>
#include <kinstance.h>
#include <kaboutdata.h>
// Others:
#include <kmessagebox.h>
#include <kmanagerselection.h>

00162 KSystemTray2::KSystemTray2(QWidget *parent, const char *name)
 : KSystemTray(parent, name)
{
}

KSystemTray2::~KSystemTray2()
{
}

00171 void KSystemTray2::displayCloseMessage(QString fileMenu)
{
      /* IDEAS OF IMPROVEMENTS:
      *  - Use queuedMessageBox() but it need a dontAskAgainName parameter
      *    and image in QMimeSourceFactory shouldn't be removed.
      *  - Sometimes the systray icon is covered (a passive popup...)
      *    Use XComposite extension, if available, to get the kicker pixmap.
      *  - Perhapse desaturate the area around the proper SysTray icon,
      *    helping bring it into sharper focus. Or draw the cicle with XOR
      *    brush.
      *  - Perhapse add the icon in the text (eg. "... in the
      *    system tray ([icon])."). Add some clutter to the dialog.
      */
#if KDE_IS_VERSION( 3, 1, 90 )
      // Don't do all the computations if they are unneeded:
      if ( ! KMessageBox::shouldBeShownContinue("hideOnCloseInfo") )
            return;
#endif
      // "Default parameter". Here, to avoid a i18n() call and dependancy in the .h
      if (fileMenu.isEmpty())
            fileMenu = i18n("File");

      // Some values we need:
      QPoint g = mapToGlobal(pos());
      int desktopWidth  = kapp->desktop()->width();
      int desktopHeight = kapp->desktop()->height();
      int tw = width();
      int th = height();

      // We are triying to make a live screenshot of the systray icon to circle it
      //  and show it to the user. If no systray is used or if the icon is not visible,
      //  we should not show that screenshot but only a text!

      // 1. Determine if the user use a system tray area or not:
      QCString screenstr;
      screenstr.setNum(qt_xscreen());
      QCString trayatom = "_NET_SYSTEM_TRAY_S" + screenstr;
      bool useSystray = (KSelectionWatcher(trayatom).owner() != None);

      // 2. And then if the icon is visible too (eg. this->show() has been called):
      useSystray = useSystray && isVisible();

      // 3. Kicker (or another systray manager) can be visible but masked out of
      //    the screen (ie. on right or on left of it). We check if the icon isn't
      //    out of screen.
      if (useSystray) {
            QRect deskRect(0, 0, desktopWidth, desktopHeight);
            if ( !deskRect.contains(g.x(), g.y()) ||
                 !deskRect.contains(g.x() + tw, g.y() + th) )
                  useSystray = false;
      }

      // 4. We raise the window containing the systray icon (typically the kicker) to
      //    have the most chances it is visible during the capture:
/*    if (useSystray) {
            // We are testing if one of the corners is hidden, and if yes, we would enter
            // a time consuming process (raise kicker and wait some time):
//          if (kapp->widgetAt(g) != this ||
//              kapp->widgetAt(g + QPoint(tw-1, 0)) != this ||
//              kapp->widgetAt(g + QPoint(0, th-1)) != this ||
//              kapp->widgetAt(g + QPoint(tw-1, th-1)) != this) {
                  int systrayManagerWinId = topLevelWidget()->winId();
                  KWin::forceActiveWindow(systrayManagerWinId);
                  kapp->processEvents(); // Because without it the systrayManager is raised only after the messageBox is displayed
//                KWin::activateWindow(systrayManagerWinId);
//                kapp->processEvents(); // Because without it the systrayManager is raised only after the messageBox is displayed
//                      KWin::raiseWindow(systrayManagerWinId);
//                kapp->processEvents(); // Because without it the systrayManager is raised only after the messageBox is displayed
                  sleep(1);
                  // TODO: Re-verify that at least one corner is now visible
//          }
      }*/

//    KMessageBox::information(this, QString::number(g.x()) + ":" + QString::number(g.y()) + ":" +
//                             QString::number((int)(kapp->widgetAt(g+QPoint(1,1)))));

      QString message = i18n(
            "<p>Closing the main window will keep %1 running in the system tray. "
            "Use <b>Quit</b> from the <b>%2</b> menu to quit the application.</p>"
                  ).arg(KGlobal::instance()->aboutData()->programName(), "Basket");
      // We are sure the systray icon is visible: ouf!
      if (useSystray) {
            // Compute size and position of the pixmap to be grabbed:
            int w = desktopWidth / 4;
            int h = desktopHeight / 9;
            int x = g.x() + tw/2 - w/2; // Center the rectange in the systray icon
            int y = g.y() + th/2 - h/2;
            if (x < 0)                 x = 0; // Move the rectangle to stay in the desktop limits
            if (y < 0)                 y = 0;
            if (x + w > desktopWidth)  x = desktopWidth - w;
            if (y + h > desktopHeight) y = desktopHeight - h;

            // Grab the desktop and draw a circle arround the icon:
            QPixmap shot = QPixmap::grabWindow(qt_xrootwin(), x, y, w, h);
            QPainter painter(&shot);
            const int CIRCLE_MARGINS = 6;
            const int CIRCLE_WIDTH   = 3;
            const int SHADOW_OFFSET  = 1;
            const int IMAGE_BORDER   = 1;
            int ax = g.x() - x - CIRCLE_MARGINS - 1;
            int ay = g.y() - y - CIRCLE_MARGINS - 1;
            painter.setPen( QPen(KApplication::palette().active().dark(), CIRCLE_WIDTH) );
            painter.drawArc(ax + SHADOW_OFFSET, ay + SHADOW_OFFSET,
                            tw + 2*CIRCLE_MARGINS, th + 2*CIRCLE_MARGINS, 0, 16*360);
            painter.setPen( QPen(Qt::red/*KApplication::palette().active().highlight()*/, CIRCLE_WIDTH) );
            painter.drawArc(ax, ay, tw + 2*CIRCLE_MARGINS, th + 2*CIRCLE_MARGINS, 0, 16*360);
#if 1
            // Draw the pixmap over the screenshot in case a window hide the icon:
            painter.drawPixmap(g.x() - x, g.y() - y + 1, *pixmap());
#endif
            painter.end();

            // Then, we add a border arround the image to make it more visible:
            QPixmap finalShot(w + 2*IMAGE_BORDER, h + 2*IMAGE_BORDER);
            finalShot.fill(KApplication::palette().active().foreground());
            painter.begin(&finalShot);
            painter.drawPixmap(IMAGE_BORDER, IMAGE_BORDER, shot);
            painter.end();

            // Associate source to image and show the dialog:
            QMimeSourceFactory::defaultFactory()->setPixmap("systray_shot", finalShot);
            KMessageBox::information(this,
                  message + "<p><center><img source=\"systray_shot\"></center></p>",
                  i18n("Docking in System Tray"), "hideOnCloseInfo");
            QMimeSourceFactory::defaultFactory()->setData("systray_shot", 0L);
      } else {
            KMessageBox::information(this,
                  message,
                  i18n("Docking in System Tray"), "hideOnCloseInfo");
      }
}

/** ContainerSystemTray */

const int Container::c_delayTooltipTime = 275;

ContainerSystemTray::ContainerSystemTray(QWidget *parent, const char *name)
 : KSystemTray2(parent, name != 0 ? name : "ContainerSystemTray"), m_parentContainer((Container*)parent)
{
      setAcceptDrops(true);

      m_showTimer = new QTimer(this);
      connect( m_showTimer, SIGNAL(timeout()), m_parentContainer, SLOT(setActive()) );

      m_autoShowTimer = new QTimer(this);
      connect( m_autoShowTimer, SIGNAL(timeout()), m_parentContainer, SLOT(setActive()) );

      // Create pixmaps for the icon:
      m_iconPixmap              = loadIcon("basket");
//    FIXME: When main window is shown at start, the icon is loaded 1 pixel too high
//           and then reloaded instantly after at the right position.
//    setPixmap(m_iconPixmap); // Load it the sooner as possible to avoid flicker
      QImage  lockedIconImage   = m_iconPixmap.convertToImage();
      QPixmap lockOverlayPixmap = loadIcon("lockoverlay");
      QImage  lockOverlayImage  = lockOverlayPixmap.convertToImage();
      KIconEffect::overlay(lockedIconImage, lockOverlayImage);
      m_lockedIconPixmap.convertFromImage(lockedIconImage);

      updateToolTip(); // Set toolTip AND icon
}

ContainerSystemTray::~ContainerSystemTray()
{
}

void ContainerSystemTray::mousePressEvent(QMouseEvent *event)
{
      if (event->button() & Qt::LeftButton) {          // Prepare drag
            m_pressPos = event->globalPos();
            m_canDrag  = true;
            event->accept();
      } else if (event->button() & Qt::MidButton) {    // Paste
            m_parentContainer->currentBasket()->pasteItem(QClipboard::Selection);
            if (Settings::usePassivePopup())
                  Global::mainContainer->showPassiveDropped(i18n("Pasted selection (%1) to basket <i>%2</i>"));
            event->accept();
      } else if (event->button() & Qt::RightButton) { // Popup menu
            KPopupMenu menu(this);
            menu.insertTitle( SmallIcon("basket"), "BasKet" );

            QPtrList<Basket> baskets = m_parentContainer->listBaskets();
            Basket *cur;
            for (uint i = 0; i < baskets.count(); ++i ) {
                  cur = baskets.at(i);
                  if ( ! cur->icon().isEmpty() )
                        menu.insertItem( SmallIconSet(cur->icon()), QString(cur->name()).replace("&", "&&"), i + 10 );
                  else
                        menu.insertItem(                            QString(cur->name()).replace("&", "&&"), i + 10 );
            }
            menu.setItemChecked( m_parentContainer->currentBasketIndex() + 10, true );
            connect( &menu, SIGNAL(activated(int)), this, SLOT(showBasket(int)) );
            menu.insertSeparator();

            m_parentContainer->actNewBasket->plug(&menu);
            menu.insertSeparator();
            m_parentContainer->actConfigGlobalShortcuts->plug(&menu);
            m_parentContainer->actAppConfig->plug(&menu);
            menu.insertSeparator();

            // Minimize / restore : since we manage the popup menu by ourself, we should do that work :
            KAction* action = actionCollection()->action("minimizeRestore");
            if (m_parentContainer->isVisible())
                  action->setText(i18n("&Minimize"));
            else
                  action->setText(i18n("&Restore"));
            action->plug(&menu);

            m_parentContainer->actQuit->plug(&menu);

            menu.exec(event->globalPos());
            event->accept();
      } else
            event->ignore();
}

void ContainerSystemTray::mouseMoveEvent(QMouseEvent *event)
{
      Basket *current = m_parentContainer->currentBasket();
      if ( m_canDrag && current->canDragItem() &&
           (m_pressPos - event->globalPos()).manhattanLength() > KApplication::startDragDistance() ) {
            Item *item = current->currentStackItem();
            current->dragStackItem();
            current->consumeStackItem(item);
            event->accept();
      } else
            event->ignore();
}

void ContainerSystemTray::mouseReleaseEvent(QMouseEvent *event)
{
      m_canDrag = false;

      if (event->button() == Qt::LeftButton)         // Show / hide main window
            if ( rect().contains(event->pos()) ) {     // Accept only if released in systemTray
                  m_parentContainer->changeActive();
                  event->accept();
            } else
                  event->ignore();
}

void ContainerSystemTray::dragEnterEvent(QDragEnterEvent *event)
{
      m_showTimer->start( Settings::dropTimeToShow() * 100, true );
      m_parentContainer->currentBasket()->showFrameInsertTo();
      m_parentContainer->setStatusBarDrag(); // FIXME: move this line in Basket::showFrameInsertTo() ?
      Basket::acceptDropEvent(event);
}

void ContainerSystemTray::dragMoveEvent(QDragMoveEvent *event)
{
      Basket::acceptDropEvent(event);
}

void ContainerSystemTray::dragLeaveEvent(QDragLeaveEvent*)
{
      m_showTimer->stop();
      m_canDrag = false;
      m_parentContainer->currentBasket()->resetInsertTo();
      m_parentContainer->resetStatusBarHint();
}

void ContainerSystemTray::dropEvent(QDropEvent *event)
{
      m_showTimer->stop();
      m_parentContainer->currentBasket()->dropEvent(event);

      if (Settings::usePassivePopup())
            Global::mainContainer->showPassiveDropped(i18n("Dropped (%1) to basket <i>%2</i>"));
}

void ContainerSystemTray::showBasket(int index)
{
      if (index >= 10)
            m_parentContainer->setCurrentBasket(index - 10);
}

/* This function comes directly from JuK: */

/*
 * This function copies the entirety of src into dest, starting in
 * dest at x and y.  This function exists because I was unable to find
 * a function like it in either QImage or kdefx
 */
static bool copyImage(QImage &dest, QImage &src, int x, int y)
{
      if(dest.depth() != src.depth())
            return false;
      if((x + src.width()) >= dest.width())
            return false;
      if((y + src.height()) >= dest.height())
            return false;

      // We want to use KIconEffect::overlay to do this, since it handles
      // alpha, but the images need to be the same size.  We can handle that.

      QImage large_src(dest);

      // It would perhaps be better to create large_src based on a size, but
      // this is the easiest way to make a new image with the same depth, size,
      // etc.

      large_src.detach();

      // However, we do have to specifically ensure that setAlphaBuffer is set
      // to false

      large_src.setAlphaBuffer(false);
      large_src.fill(0); // All transparent pixels
      large_src.setAlphaBuffer(true);

      int w = src.width();
      int h = src.height();
      for(int dx = 0; dx < w; dx++)
            for(int dy = 0; dy < h; dy++)
                  large_src.setPixel(dx + x, dy + y, src.pixel(dx, dy));

      // Apply effect to image

      KIconEffect::overlay(dest, large_src);

      return true;
}

void ContainerSystemTray::updateToolTip()
{
      Basket *basket = m_parentContainer->currentBasket();

      if (basket->icon().isEmpty() || ! Settings::showIconInSystray())
            setPixmap(basket->isLocked() ? m_lockedIconPixmap : m_iconPixmap);
      else {
            // Code that comes from JuK:
            QPixmap bgPix = loadIcon("basket");
            QPixmap fgPix = SmallIcon(basket->icon());

            QImage bgImage = bgPix.convertToImage(); // Probably 22x22
            QImage fgImage = fgPix.convertToImage(); // Should be 16x16
            QImage lockOverlayImage = loadIcon("lockoverlay").convertToImage();

            KIconEffect::semiTransparent(bgImage);
            copyImage(bgImage, fgImage, (bgImage.width() - fgImage.width()) / 2,
                        (bgImage.height() - fgImage.height()) / 2);
            if (basket->isLocked())
                  KIconEffect::overlay(bgImage, lockOverlayImage);

            bgPix.convertFromImage(bgImage);
            setPixmap(bgPix);
      }

      //QTimer::singleShot( Container::c_delayTooltipTime, this, SLOT(updateToolTipDelayed()) );
      // No need to delay: it's be called when items are changed:
      updateToolTipDelayed();
}

void ContainerSystemTray::updateToolTipDelayed()
{
      Basket *basket = m_parentContainer->currentBasket();
      Item   *item   = basket->currentStackItem();

      QString tip = "<p>" + ( basket->isLocked() ? kapp->makeStdCaption(i18n("%1 (Locked)"))
                                                 : kapp->makeStdCaption(     "%1")          )
                                                 .arg(Basket::textToHTMLWithoutP(basket->name()));

      if (basket->canDragItem()) {
            tip += "<br>" + i18n("%1 item to drag (%2):")
                   .arg( basket->stackTakeAtEnd() ? i18n("Last") : i18n("First") )
                   .arg( item->typeName() ) + "<br>";
            tip += item->toHtml("_tooltip_image_");
      } else if (basket->isEmpty() && basket->isAStack())
            tip += "<br>" + i18n("(Empty)");

      QToolTip::add(this, tip);
/*    if (Gobal::debugWindow)
            *Global::debugWindow << "<b>Info :</b>\tSystem tray icon tooltip updated : " + tip;*/
}

void ContainerSystemTray::wheelEvent(QWheelEvent *event)
{
      m_parentContainer->wheelEvent(event);
}

void ContainerSystemTray::enterEvent(QEvent*)
{
      if (Settings::showOnMouseIn())
            m_autoShowTimer->start(Settings::timeToShowOnMouseIn() * 100, true );
}

void ContainerSystemTray::leaveEvent(QEvent*)
{
      m_autoShowTimer->stop();
}

/** ContainerTabBar */

00564 ContainerTabBar::ContainerTabBar(QWidget *parent, const char *name)
 : QTabBar(parent, name != 0 ? name : "ContainerTabBar")
{
      setAcceptDrops(true);
      m_basketIndexToMove  = -1;
      m_pointedBasket      = 0;
      m_pointedBasketIndex = -1;
      m_ttGroup            = 0L;
      m_showTimer          = new QTimer(this);
      connect( m_showTimer, SIGNAL(timeout()), this, SLOT(timeout()) );
}

ContainerTabBar::~ContainerTabBar()
{
}

int ContainerTabBar::tabIndexForCursorPosition(const QPoint &curPos)
{
      QTab *tab;

      for ( int i = 0; i < count(); ++i ) {
            tab = tabAt(i);
            if (tab->rect().contains(curPos))
                  return i;
      }

      return -1;
}

// FIXME TODO: addTab(QWidget, index, icon, text, toolTip)...

void ContainerTabBar::updateToolTips(const QStringList &tips)
{
      if (tips.count() != (uint)count())
            return; // Should throw an exception or...

      QTab *tab;

      delete m_ttGroup;                    // It delete all toolTips for this widget
      m_ttGroup = new QToolTipGroup(this); // Then we can assign new toolTips
      for ( int i = 0; i < count(); ++i ) {
            tab = tabAt(i);
            QToolTip::add(this, tab->rect(), *(tips.at(i)), m_ttGroup, QString());
      }
}

void ContainerTabBar::contextMenuEvent(QContextMenuEvent *event)
{
      if (event->reason() == QContextMenuEvent::Mouse) {   // With mouse : find which tab is under the mouse
            int index = tabIndexForCursorPosition(event->pos());
            emit wantContextMenu(index, event->globalPos()); // Even if index == -1 : this case will be treated
      } else {                                             // With keyboard : use the current tab
            QRect rect = tab(currentTab())->rect();          // Show popup menu on bottom /*middle*/ of the current tab
            rect.moveTopLeft( mapToGlobal(tab(currentTab())->rect().topLeft()) );
            emit wantContextMenu(indexOf(currentTab()), rect);
      }
}

void ContainerTabBar::dragEnterEvent(QDragEnterEvent*)
{
      Global::mainContainer->setStatusBarDrag();
}

void ContainerTabBar::dragMoveEvent(QDragMoveEvent *event) // FIXME: Duplicate code (3 times)
{
      bool isHoverTab = false; // If a tab exist under cursor
      Basket *currentlyPointedBasket = 0;

      int index = tabIndexForCursorPosition(event->pos());
      if (index != -1) {
            isHoverTab = true;
            currentlyPointedBasket = Global::mainContainer->basketAt(index);
            if (index != m_pointedBasketIndex) { // If mouse point a new basket, restart timer for this basket
                  m_showTimer->start( Settings::dropTimeToShow() * 100, true);
                  m_pointedBasketIndex = index;
            }
      }

      // If cursor moved to another tab or not, show a feedback for the new basket and delete the one for the old :
      if (m_pointedBasket != currentlyPointedBasket) {
            if (m_pointedBasket != 0)
                  m_pointedBasket->resetInsertTo();
            if (currentlyPointedBasket != 0)
                  currentlyPointedBasket->showFrameInsertTo();
            m_pointedBasket = currentlyPointedBasket;
      }

      Basket::acceptDropEvent( event, isHoverTab && ! m_pointedBasket->isLocked() );
}

void ContainerTabBar::dragLeaveEvent(QDragLeaveEvent*)
// TODO: showPage(theLastShownBeforeDragEnterEvent); ?
{
      m_showTimer->stop();

      m_pointedBasket->resetInsertTo();
      Global::mainContainer->resetStatusBarHint();
      m_pointedBasket = 0;
      m_pointedBasketIndex = -1;
}

void ContainerTabBar::dropEvent(QDropEvent *event)
{
      m_showTimer->stop();

      m_pointedBasket->dropEvent(event);
      m_pointedBasket = 0;
      m_pointedBasketIndex = -1;
}

void ContainerTabBar::timeout()
{
      emit wantShowPage(m_pointedBasketIndex);
}

void ContainerTabBar::mousePressEvent(QMouseEvent *event)
{
      QTabBar::mousePressEvent(event);

      if (event->button() & Qt::LeftButton)
            m_basketIndexToMove = tabIndexForCursorPosition(event->pos());
      else if (event->button() & Qt::MidButton) {
            int index = tabIndexForCursorPosition(event->pos());
            if (index != -1)
                  emit wantPaste(index, QClipboard::Selection);
      }
}

void ContainerTabBar::mouseMoveEvent(QMouseEvent *event)
{
      int newIndex = tabIndexForCursorPosition(event->pos());

      if ( (m_basketIndexToMove != -1) && // eg. The pressed button is well the right one
           (newIndex != -1) && (newIndex != m_basketIndexToMove)) {
            Global::mainContainer->changeBasketPlace(m_basketIndexToMove, newIndex);
            m_basketIndexToMove = newIndex;
            QCursor::setPos( mapToGlobal(tabAt(newIndex)->rect().center()) );
      }
}

void ContainerTabBar::mouseReleaseEvent(QMouseEvent*)
{
      m_basketIndexToMove = -1;
}

void ContainerTabBar::mouseDoubleClickEvent(QMouseEvent *event)
{
      if (event->button() & Qt::LeftButton) {
            int index = tabIndexForCursorPosition(event->pos());
            if (index != -1)
                  emit doubleClicked(index);
      }
}

/** ContainerTabWidget */

00720 ContainerTabWidget::ContainerTabWidget(QWidget *parent, const char *name)
 : QTabWidget(parent, name != 0 ? name : "ContainerTabWidget")
{
      ContainerTabBar *tabBar = new ContainerTabBar(this);
      setTabBar(tabBar);

      connect( tabBar, SIGNAL(doubleClicked(int)),                  this, SLOT(slotDoubleClicked(int))               );
      connect( tabBar, SIGNAL(wantPaste(int, QClipboard::Mode)),    this, SLOT(slotWantPaste(int, QClipboard::Mode)) );
      connect( tabBar, SIGNAL(wantContextMenu(int, const QPoint&)), this, SLOT(slotContextMenu(int, const QPoint&))  );
      connect( tabBar, SIGNAL(wantContextMenu(int, const QRect&)),  this, SLOT(slotContextMenu(int, const QRect&))   );
      connect( tabBar, SIGNAL(wantShowPage(int)),                   this, SLOT(setCurrentPage(int))                  );
}

/* We overload it to not try to show a page that is already shown
 * Cause problems when dragging over a tab while an inline editor in open:
 *  the "Ctrl+DND: copy..." message is replaced by "Editing. Press Escape..."
 *  when setCurrentPage(int) is called by the timer.
 * FIXME: This is just a workaround that doesn't work in all cases...
 */
void ContainerTabWidget::setCurrentPage(int index)
{
      if (currentPageIndex() != index)
            QTabWidget::setCurrentPage(index);
}

void ContainerTabWidget::updateToolTips(const QStringList &tips)
{
      ((ContainerTabBar*)tabBar())->updateToolTips(tips);
}

ContainerTabWidget::~ContainerTabWidget()
{
}

void ContainerTabWidget::slotDoubleClicked(int tabIndex)
{
      emit doubleClicked(tabIndex);
}

void ContainerTabWidget::slotContextMenu(int tabIndex, const QPoint &globalPos)
{
      emit contextMenu(tabIndex, globalPos);
}

void ContainerTabWidget::slotContextMenu(int tabIndex, const QRect  &globalRect)
{
      emit contextMenu(tabIndex, globalRect);
}

void ContainerTabWidget::slotWantPaste(int tabIndex, QClipboard::Mode mode)
{
      emit wantPaste(tabIndex, mode);
}

void ContainerTabWidget::contextMenuEvent(QContextMenuEvent *event)
{
      // Since contextMenuEvent is triggered ONLY when clicking tabs in QTabBar,
      //  theire is no way to have context menu triggered by clicking on EMPTY tab bar.
      //  It's why we react here.
      if ( (tabBar()->y()                      <= event->pos().y()) &&
           (tabBar()->y() + tabBar()->height() >  event->pos().y())    )
            emit contextMenu(-1, event->globalPos());
}

/** Container */

00786 Container::Container(QWidget *parent, const char *name)
 : KMainWindow(parent, name != 0 ? name : "BasketsContainer"), m_passivePopup(0L)
{
      setCentralWidget(new QWidget(this));
      m_layout = new QVBoxLayout(centralWidget());
      m_tab    = new ContainerTabWidget(centralWidget());
      m_layout->addWidget(m_tab);

      setupActions();
      setupStatusBar();
      createGUI();
      setAutoSaveSettings();

      m_actShowMenubar->setChecked(   menuBar()->isShown()   );
      m_actShowToolbar->setChecked(   toolBar()->isShown()   );
      m_actShowStatusbar->setChecked( statusBar()->isShown() );

      Global::mainContainer = this; // FIXME: Needed for the uggly hack in Basket:: setupActions() :-/
      loadBaskets();                // TODO:  Parent baskets to a container ?

      connect( m_tab, SIGNAL(doubleClicked(int)),               this, SLOT(propBasket(int))                      );
      connect( m_tab, SIGNAL(contextMenu(int, const QPoint&)),  this, SLOT(contextMenu(int, const QPoint&))      );
      connect( m_tab, SIGNAL(contextMenu(int, const QRect&)),   this, SLOT(contextMenu(int, const QRect&))       );
      connect( m_tab, SIGNAL(wantPaste(int, QClipboard::Mode)), this, SLOT(pasteToBasket(int, QClipboard::Mode)) );
      connect( m_tab, SIGNAL(currentChanged(QWidget*)),         this, SLOT(tabChanged(QWidget*))                 );

      m_tryHideTimer = new QTimer(this);
      m_hideTimer    = new QTimer(this);
      connect( m_tryHideTimer, SIGNAL(timeout()), this, SLOT(timeoutTryHide()) );
      connect( m_hideTimer,    SIGNAL(timeout()), this, SLOT(timeoutHide())    );
}

Container::~Container()
{
      delete m_colorPicker;
}

void Container::setupStatusBar()
{
      statusBar()->show();
      statusBar()->setSizeGripEnabled(true);

      m_basketStatus = new QLabel(this);
      m_basketStatus->setSizePolicy( QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored, 0, 0, false) );

      statusBar()->addWidget( m_basketStatus, 1, false ); // Fit all extra space and is hiddable

      m_selectionStatus = new QLabel(this);
      statusBar()->addWidget( m_selectionStatus, 0, true );

      m_lockStatus = new ClickableLabel(this);
      m_lockStatus->setMinimumSize(18, 18);
      m_lockStatus->setAlignment(Qt::AlignCenter);
      statusBar()->addWidget( m_lockStatus, 0, true );
      connect( m_lockStatus, SIGNAL(clicked()), this, SLOT(lockBasket()) );
}

00843 void Container::setupActions()
{
      // KActionCollection *ac = actionCollection();
      // KAction           *a;

      m_goBasketsMapper = new QSignalMapper(this);
      connect( m_goBasketsMapper, SIGNAL(mapped(int)), this, SLOT(setCurrentBasket(int)) );

      /** Basket : **************************************************************/

      actNewBasket    = new KAction( i18n("&New..."), "filenew", KStdAccel::shortcut(KStdAccel::New),
                                     this, SLOT(askNewBasket()), actionCollection(), "basket_new" );

      m_actPropBasket = new KAction( i18n("&Properties..."), "misc", "F2",
                                     this, SLOT(propBasket()), actionCollection(), "basket_properties" );
      m_actDelBasket  = new KAction( i18n("&Remove"), "tab_remove", 0,
                                     this, SLOT(delBasket()), actionCollection(), "basket_delete" );
      m_actLockBasket = new KToggleAction( i18n("&Lock"), "encrypted", "Ctrl+L",
                                           this, SLOT(lockBasket()), actionCollection(), "basket_lock" );

      m_actClearStack = new KAction( i18n("&Clear Stack"), "editclear", 0,
                                     this, SLOT(clearCurrentStack()), actionCollection(), "stack_clear" );
      m_actOpenMirror = new KAction( i18n("&Open the Mirrored Folder"), "fileopen", 0,
                                     this, SLOT(openCurrentMirror()), actionCollection(), "mirror_open" );
      /*m_actReloadMirror = KStdAction::redisplay(this, SLOT(reloadCurrentMirror()), actionCollection(), "mirror_reload" );
      m_actReloadMirror->setText(i18n("&Reload Folder Contents"));
      m_actReloadMirror->setShortcut( KStdAccel::shortcut(KStdAccel::Reload) ); // See Bug 85867*/

      new KAction( i18n("&Export to HTML..."), "fileexport", 0,
                   this, SLOT(exportToHTML()), actionCollection(), "basket_export_html" );
      new KAction( i18n("&KNotes"), "knotes", 0,
                   this, SLOT(importKNotes()), actionCollection(), "basket_import_knotes" );
      new KAction( i18n("K&Jots"), "kjots", 0,
                   this, SLOT(importKJots()), actionCollection(), "basket_import_kjots" );
      new KAction( i18n("&Sticky Notes"), "gnome", 0,
                   this, SLOT(importStickyNotes()), actionCollection(), "basket_import_sticky_notes" );

      m_actHideWindow = new KAction( i18n("&Hide Window"), "fileclose", KStdAccel::shortcut(KStdAccel::Close),
                                     this, SLOT(hideOnEscape()), actionCollection(), "window_hide" );
      m_actHideWindow->setEnabled(Settings::useSystray()); // Init here !
      actQuit         = KStdAction::quit( this, SLOT(askForQuit()), actionCollection() );

      /** Edit : ****************************************************************/

      //m_actUndo     = KStdAction::undo(  this, SLOT(undo()),                 actionCollection() );
      //m_actUndo->setEnabled(false); // Not yet implemented !
      //m_actRedo     = KStdAction::redo(  this, SLOT(redo()),                 actionCollection() );
      //m_actRedo->setEnabled(false); // Not yet implemented !

      m_actCutItem  = KStdAction::cut(   this, SLOT(cutItem()),              actionCollection() );
      m_actCopyItem = KStdAction::copy(  this, SLOT(copyItem()),             actionCollection() );
#if KDE_IS_VERSION( 3, 1, 90 ) // KDE 3.2.x
      m_actPaste    = KStdAction::pasteText( this, SLOT(pasteInCurrentBasket()), actionCollection() );
#else
      m_actPaste    = KStdAction::paste(     this, SLOT(pasteInCurrentBasket()), actionCollection() );
#endif
      m_actDelItem  = new KAction( i18n("D&elete"), "editdelete", "Delete",
                                  this, SLOT(delItem()), actionCollection(), "edit_delete" );

      m_actSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ), actionCollection() );
      m_actSelectAll      ->setStatusText( i18n( "Selects all items" ) );
      m_actUnselectAll = new KAction( i18n( "U&nselect All" ), CTRL+Key_U, this, SLOT( slotUnselectAll() ),
                                      actionCollection(), "edit_unselect_all" );
      m_actUnselectAll    ->setStatusText( i18n( "Unselects all selected items" ) );
      m_actInvertSelection = new KAction( i18n( "&Invert Selection" ), CTRL+Key_Asterisk,
                                          this, SLOT( slotInvertSelection() ),
                                          actionCollection(), "edit_invert_selection" );
      m_actInvertSelection->setStatusText( i18n( "Inverts the current selection of items" ) );
      m_actSelectCheckedItems = new KAction( i18n( "Select Chec&ked Items" ), 0,
                                             this, SLOT( slotSelectCheckedItems() ),
                                             actionCollection(), "edit_select_checked_items" );

      m_actShowSearch  = new KToggleAction( i18n("Show Search &Bar"), "find", KStdAccel::shortcut(KStdAccel::Find),
                                             /*this, SLOT(showHideSearchBar()),*/ actionCollection(), "edit_show_search" );
      connect( m_actShowSearch, SIGNAL(toggled(bool)), this, SLOT(showHideSearchBar(bool)) );
      m_actResetSearch = new KAction( i18n( "&Reset Search" ), "locationbar_erase", "Ctrl+R",
                                      this, SLOT( slotResetSearch() ),
                                      actionCollection(), "edit_reset_search" );

      /** Go : ******************************************************************/

      m_actPreviousBasket = KStdAction::back( this, SLOT(goToPreviousBasket()), actionCollection() );
      m_actPreviousBasket->setText(i18n("&Previous Basket"));
      m_actNextBasket     = KStdAction::forward( this, SLOT(goToNextBasket()), actionCollection() );
      m_actNextBasket->setText(i18n("&Next Basket"));

      m_actPrevChecked   = new KAction( i18n("Pre&vious Checked Item"),   "", "",
                                        this, SLOT(goToPreviousCheckedItem()),   actionCollection(), "go_prev_checked"   );
      m_actNextChecked   = new KAction( i18n("Ne&xt Checked Item"),       "", "Ctrl+E",
                                        this, SLOT(goToNextCheckedItem()),       actionCollection(), "go_next_checked"   );
      m_actPrevUnchecked = new KAction( i18n("Previ&ous Unchecked Item"), "", "",
                                        this, SLOT(goToPreviousUncheckedItem()), actionCollection(), "go_prev_unchecked" );
      m_actNextUnchecked = new KAction( i18n("Next &Unchecked Item"),     "", "Ctrl+Shift+E",
                                        this, SLOT(goToNextUncheckedItem()),     actionCollection(), "go_next_unchecked" );

      /** Items : ***************************************************************/

      m_actEditItem         = new KAction( i18n("Verb; not Menu", "&Edit..."), "edit",   "Return",
                                           this, SLOT(editItem()), actionCollection(), "item_edit" );
      m_actEditItemMetaData = new KAction( i18n("Edit &Meta-data..."),         "attach", "Shift+Return",
                                           this, SLOT(editItemMetaData()), actionCollection(), "item_edit_meta_data" );

      m_actOpenItem         = KStdAction::open( this, SLOT(openItem()), actionCollection(), "item_open" );
      m_actOpenItem->setText(i18n("&Open"));
      m_actOpenItem->setShortcut("F9");
      m_actOpenItemWith     = new KAction( i18n("Open &With..."), "fileopen", "Shift+F9",
                                       this, SLOT(openItemWith()), actionCollection(), "item_open_with" );
      m_actSaveItemAs       = KStdAction::saveAs( this, SLOT(saveItemAs()), actionCollection(), "item_save_as" );
//    m_actSaveItemAs->setText("Save &a Copy As...");
      m_actSaveItemAs->setShortcut(KStdAccel::save());

      // FIXME: I don't know if "checkedbox" is part of CrystalSVG icon pack or if it's a KOffice (or other app) icon
      //  "checkmark" could also be used. And if theire is none, "button_ok" is graphically near !
      m_actCheckItems = new KToggleAction( i18n("Chec&k"), "checkedbox", "Ctrl+K",
                                           this, SLOT(checkItem()), actionCollection(), "item_check" );

      m_actMoveOnTop    = new KAction( i18n("Move on &Top"),    "top",    "Ctrl+Shift+Home",
                                       this, SLOT(moveOnTop()),    actionCollection(), "item_move_top" );
      m_actMoveItemUp   = new KAction( i18n("Move &Up"),        "up",     "Ctrl+Shift+Up",
                                       this, SLOT(moveItemUp()),   actionCollection(), "item_move_up" );
      m_actMoveItemDown = new KAction( i18n("Move &Down"),      "down",   "Ctrl+Shift+Down",
                                       this, SLOT(moveItemDown()), actionCollection(), "item_move_down" );
      m_actMoveOnBottom = new KAction( i18n("Move on &Bottom"), "bottom", "Ctrl+Shift+End",
                                       this, SLOT(moveOnBottom()), actionCollection(), "item_move_bottom" );

      /** Insert : **************************************************************/

      QSignalMapper *insertEmptyMapper  = new QSignalMapper(this);
      QSignalMapper *insertWizardMapper = new QSignalMapper(this);
      connect( insertEmptyMapper,  SIGNAL(mapped(int)), this, SLOT(insertEmpty(int))  );
      connect( insertWizardMapper, SIGNAL(mapped(int)), this, SLOT(insertWizard(int)) );

      m_actInsertText   = new KAction( i18n("&Text"),      "text",     "Ctrl+T", actionCollection(), "insert_text"     );
      m_actInsertHtml   = new KAction( i18n("&Rich Text"), "html",     "Ctrl+H", actionCollection(), "insert_html"     );
      m_actInsertLink   = new KAction( i18n("&Link"),      "link",     "Ctrl+Y", actionCollection(), "insert_link"     );
      m_actInsertImage  = new KAction( i18n("&Image"),     "image",    "",       actionCollection(), "insert_image"    );
      m_actInsertColor  = new KAction( i18n("&Color"),     "colorset", "",       actionCollection(), "insert_color"    );
      m_actInsertLauncher=new KAction( i18n("L&auncher"),  "launch",   "",       actionCollection(), "insert_launcher" );

      m_actImportKMenu  = new KAction(i18n("Import &KMenu Launcher..."),"kmenu", "",actionCollection(),"insert_kmenu"      );
      m_actImportIcon   = new KAction( i18n("Im&port an Icon..."),  "icons",     "",actionCollection(),"insert_icon"       );
      m_actLoadFile     = new KAction( i18n("Load From a &File..."),"fileimport","",actionCollection(),"insert_from_file"  );
      //m_actMirrorFile   = new KAction( i18n("&Mirror a File..."),   "wizard",    "",actionCollection(),"insert_mirror_file");

      connect( m_actInsertText,     SIGNAL(activated()), insertEmptyMapper, SLOT(map()) );
      connect( m_actInsertHtml,     SIGNAL(activated()), insertEmptyMapper, SLOT(map()) );
      connect( m_actInsertImage,    SIGNAL(activated()), insertEmptyMapper, SLOT(map()) );
      connect( m_actInsertLink,     SIGNAL(activated()), insertEmptyMapper, SLOT(map()) );
      connect( m_actInsertColor,    SIGNAL(activated()), insertEmptyMapper, SLOT(map()) );
      connect( m_actInsertLauncher, SIGNAL(activated()), insertEmptyMapper, SLOT(map()) );
      insertEmptyMapper->setMapping(m_actInsertText,     Item::Text    );
      insertEmptyMapper->setMapping(m_actInsertHtml,     Item::Html    );
      insertEmptyMapper->setMapping(m_actInsertImage,    Item::Image   );
      insertEmptyMapper->setMapping(m_actInsertLink,     Item::Link    );
      insertEmptyMapper->setMapping(m_actInsertColor,    Item::Color   );
      insertEmptyMapper->setMapping(m_actInsertLauncher, Item::Launcher);

      connect( m_actImportKMenu, SIGNAL(activated()), insertWizardMapper, SLOT(map()) );
      connect( m_actImportIcon,  SIGNAL(activated()), insertWizardMapper, SLOT(map()) );
      connect( m_actLoadFile,    SIGNAL(activated()), insertWizardMapper, SLOT(map()) );
      //connect( m_actMirrorFile,  SIGNAL(activated()), insertWizardMapper, SLOT(map()) );
      insertWizardMapper->setMapping(m_actImportKMenu,  1 );
      insertWizardMapper->setMapping(m_actImportIcon,   2 );
      insertWizardMapper->setMapping(m_actLoadFile,     3 );
      //insertWizardMapper->setMapping(m_actMirrorFile,   4 );

      m_colorPicker = new DesktopColorPicker();
      m_actColorPicker = new KAction( i18n("C&olor From Screen"), "kcolorchooser", "",
                                       this, SLOT(slotColorFromScreen()), actionCollection(), "insert_screen_color" );
      connect( m_colorPicker, SIGNAL(pickedColor(const QColor&)), this, SLOT(colorPicked(const QColor&)) );
      connect( m_colorPicker, SIGNAL(canceledPick()),             this, SLOT(colorPickingCanceled())     );

      m_insertActions.append( m_actInsertText     );
      m_insertActions.append( m_actInsertHtml     );
      m_insertActions.append( m_actInsertLink     );
      m_insertActions.append( m_actInsertImage    );
      m_insertActions.append( m_actInsertColor    );
      m_insertActions.append( m_actImportKMenu    );
      m_insertActions.append( m_actInsertLauncher );
      m_insertActions.append( m_actImportIcon     );
      m_insertActions.append( m_actLoadFile       );
      //m_insertActions.append( m_actMirrorFile     );
      m_insertActions.append( m_actColorPicker    );

      /** Settings : ************************************************************/

      m_actShowMenubar   = KStdAction::showMenubar(   this, SLOT(toggleMenuBar()),   actionCollection());
      m_actShowToolbar   = KStdAction::showToolbar(   this, SLOT(toggleToolBar()),   actionCollection());
    m_actShowStatusbar = KStdAction::showStatusbar( this, SLOT(toggleStatusBar()), actionCollection());

      (void) KStdAction::keyBindings( this, SLOT(showShortcutsSettingsDialog()), actionCollection() );

      actConfigGlobalShortcuts = KStdAction::keyBindings(this, SLOT(showGlobalShortcutsSettingsDialog()),
                                                         actionCollection(), "options_configure_global_keybinding");
      actConfigGlobalShortcuts->setText(i18n("Configure &Global Shortcuts..."));

      (void) KStdAction::configureToolbars(this, SLOT(configureToolbars()), actionCollection() );

      //KAction *actCfgNotifs = KStdAction::configureNotifications(this, SLOT(configureNotifications()), actionCollection() );
      //actCfgNotifs->setEnabled(false); // Not yet implemented !

      actAppConfig = KStdAction::preferences( this, SLOT(showSettingsDialog()), actionCollection() );
}

void Container::rebuildBasketsMenu()
{
      unplugActionList( QString::fromLatin1("baskets_list") );
      actBasketsList.clear();

      QPtrList<Basket> baskets = listBaskets();
      Basket *cur;
      KToggleAction *action;
      for (uint i = 0; i < baskets.count(); ++i ) {
            cur = baskets.at(i);
            if ( cur->icon().isEmpty() )
                  action = new KToggleAction( QString(cur->name()).replace("&", "&&"),              0, m_goBasketsMapper, SLOT(map()), 0 );
            else
                  action = new KToggleAction( QString(cur->name()).replace("&", "&&"), cur->icon(), 0, m_goBasketsMapper, SLOT(map()), 0 );
            if (i == currentBasketIndex())
                  action->setChecked(true);
            m_goBasketsMapper->setMapping(action, i);
            actBasketsList.append(action);
      }

      plugActionList( QString::fromLatin1("baskets_list"), actBasketsList);
}

QPopupMenu* Container::popupMenu(const QString &menuName)
{
      return (QPopupMenu *)factory()->container(menuName, this);
}

// Redirected actions :

void Container::clearCurrentStack()         { currentBasket()->clearStack();                      }
void Container::openCurrentMirror()         { currentBasket()->openMirroredFolder();              }
void Container::reloadCurrentMirror()       { currentBasket()->reloadMirroredFolder();            }
void Container::exportToHTML()              { currentBasket()->exportToHTML();                    }
01081 void Container::editItem()                  { currentBasket()->editItem();                        }
void Container::editItemMetaData()          { currentBasket()->editItemMetaData();                }
void Container::delItem()                   { currentBasket()->delItem();                         }
void Container::copyItem()                  { currentBasket()->copyItem();                        }
void Container::cutItem()                   { currentBasket()->cutItem();                         }
void Container::openItem()                  { currentBasket()->openItem();                        }
void Container::openItemWith()              { currentBasket()->openItemWith();                    }
void Container::saveItemAs()                { currentBasket()->saveItemAs();                      }
void Container::checkItem()                 { currentBasket()->checkItem();                       }
void Container::moveOnTop()                 { currentBasket()->moveOnTop();                       }
void Container::moveOnBottom()              { currentBasket()->moveOnBottom();                    }
void Container::moveItemUp()                { currentBasket()->moveItemUp();                      }
void Container::moveItemDown()              { currentBasket()->moveItemDown();                    }
void Container::slotSelectAll()             { currentBasket()->selectAll();                       }
void Container::slotUnselectAll()           { currentBasket()->unselectAll();                     }
void Container::slotInvertSelection()       { currentBasket()->invertSelection();                 }
void Container::slotSelectCheckedItems()    { currentBasket()->selectCheckedItems();              }

void Container::goToPreviousCheckedItem()   { currentBasket()->gotoNextCheckedItem(false, true);  }
void Container::goToNextCheckedItem()       { currentBasket()->gotoNextCheckedItem(true,  true);  }
void Container::goToPreviousUncheckedItem() { currentBasket()->gotoNextCheckedItem(false, false); }
void Container::goToNextUncheckedItem()     { currentBasket()->gotoNextCheckedItem(true,  false); }

void Container::slotResetSearch()           { currentDecoratedBasket()->resetSearch();            }

void Container::importKJots()
{
      QString dirPath = locateLocal("appdata","") + "/../kjots/"; // I thing the assumption is good
      QDir dir(dirPath, QString::null, QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::NoSymLinks);

      QStringList list = dir.entryList();
      bool wasImported = false;
      for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { // For each file
            QFile file(dirPath + *it);
            if (file.open(IO_ReadOnly)) {
                  QTextStream stream(&file);
                  stream.setEncoding(QTextStream::Locale);

                  QString buf = stream.readLine();
                  if ( !buf.isNull() && buf.left(9) == "\\NewEntry") {

                        // First create a basket for it:
                        QString basketFolder = BasketFactory::createBasketClips( KURL(file.name()).fileName() );
                        Basket *basket = loadBasket(basketFolder);
                        basket->setIcon("kjots");
                        basket->save(); // In case no item is added after that

                        QString title, body;
                        bool haveAnEntry = false;
                        while (1) {
                              if (buf.left(9) == "\\NewEntry") {
                                    if (haveAnEntry) { // Do not add item the first time
                                          Item *item = ItemFactory::createItemText(title, basket);
                                          item->setTextStyle(item->textFontType(), QColor("#110099"));
                                          ItemFactory::createItemText(body, basket);
                                    }
                                    title = buf.mid(10, buf.length());          // Problem : basket will be saved
                                    body = ""; // New item will then be created //  EACH time an item is imported
                                    haveAnEntry = true;
                                    wasImported = true;
                              } else if (buf.left(3) != "\\ID") { // Don't care of the ID
                                    // Remove escaped '\' characters and append the text to the body
                                    int pos = 0;
                                    while ( (pos = buf.find('\\', pos)) != -1 )
                                          if (buf[++pos] == '\\')
                                                buf.remove(pos, 1 );
                                    body.append(buf + "\n");
                              }
                              buf = stream.readLine();
                              if (buf.isNull()) // OEF
                                    break;
                        }
                        // Add the ending item (there isn't any other "\\NewEntry" to do it):
                        if (haveAnEntry) {
                              Item *item = ItemFactory::createItemText(title, basket);
                              item->setTextStyle(item->textFontType(), QColor("#110099"));
                              ItemFactory::createItemText(body, basket);
                        }
                  }
                  file.close();
            }
      }
}

void Container::importKNotes()
{
      QString dirPath = locateLocal("appdata","") + "/../knotes/"; // I thing the assumption is good
      QDir dir(dirPath, QString::null, QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::NoSymLinks);

      QStringList list = dir.entryList();
      bool wasImported = false;
      for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { // For each file
            if ( ! (*it).endsWith(".ics") ) // Don't process *.ics~ and otehr files
                  continue;
            QFile file(dirPath + *it);
            if (file.open(IO_ReadOnly)) {
                  QTextStream stream(&file);
                  stream.setEncoding(QTextStream::UnicodeUTF8);

                  // First create a basket for it:
                  QString basketFolder = BasketFactory::createBasketClips( i18n("Notes from KNotes") );
                  Basket *basket = loadBasket(basketFolder);
                  basket->setIcon("knotes");
                  basket->save(); // In case no item is added after that

                  bool inVJournal    = false;
                  bool inDescription = false;

                  QString title, body;
                  QString buf;
                  while (1) {
                        buf = stream.readLine();
                        if (buf.isNull()) // OEF
                              break;

                        if ( !buf.isNull() && buf == "BEGIN:VJOURNAL") {
                              inVJournal = true;
                        } else if (inVJournal && buf.startsWith("SUMMARY:")) {
                              title = buf.mid(8, buf.length());
                        } else if (inVJournal && buf.startsWith("DESCRIPTION:")) {
                              body = buf.mid(12, buf.length());
                              inDescription = true;
                        } else if (inDescription && buf.startsWith(" ")) {
                              body += buf.mid(1, buf.length());
                        } else if (buf == "END:VJOURNAL") {
                              Item *item = ItemFactory::createItemText(fromICS(title), basket);
                              item->setTextStyle(item->textFontType(), QColor("#110099"));
                              if (body.startsWith("<html>")) // FIXME: Assumption not always true
                                    ItemFactory::createItemHtml(fromICS(body), basket);
                              else
                                    ItemFactory::createItemText(fromICS(body), basket);
                              wasImported   = true;
                              inVJournal    = false;
                              inDescription = false;
                              title = "";
                              body = "";
                        } else
                              inDescription = false;
                  }

                  // Bouh : duplicate code
                  // In case of unvalide ICAL file!
                  if ( ! body.isEmpty() ) { // Add the ending item
                        Item *item = ItemFactory::createItemText(fromICS(title), basket);
                        item->setTextStyle(item->textFontType(), QColor("#110099"));
                        if (body.startsWith("<html>")) // FIXME: Assumption not always true
                              ItemFactory::createItemHtml(fromICS(body), basket);
                        else
                              ItemFactory::createItemText(fromICS(body), basket);
                        wasImported = true;
                  }
                  file.close();
            }
      }
}

QString Container::fromICS(const QString &ics)
{
      QString result = ics;

      // Remove escaped '\' characters and append the text to the body
      int pos = 0;
      while ( (pos = result.find('\\', pos)) != -1 ) {
            if ((uint)pos == result.length() - 1) // End of string
                  break;
            if (result[pos+1] == 'n') {
                  result.replace(pos, 2, '\n');
            } else if (result[pos+1] == 'r') {
                  result.replace(pos, 2, '\r');
            } else if (result[pos+1] == 't') {
                  result.replace(pos, 2, '\t');
            } else if (result[pos] == '\\') {
                  result.remove(pos, 1); // Take care of "\\", "\,", "\;" and other escaped characters I haven't noticed
                  ++pos;
            }
      }

      return result;
}

void Container::importStickyNotes()
{
      // Sticky Notes file is usually located in ~/.gnome2/stickynotes_applet
      // We will search all directories in "~/" that contain "gnome" in the name,
      // and will search for "stickynotes_applet" file (that should be XML file with <stickynotes> root.
      QDir dir(QDir::home().absPath(), QString::null, QDir::Name | QDir::IgnoreCase,
               QDir::Dirs | QDir::NoSymLinks | QDir::Hidden);
      QStringList founds;

      QStringList list = dir.entryList();
      bool wasImported = false;
      for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { // For each folder
            if ( (*it).contains("gnome", false) ) {
                  QString fullPath = QDir::home().absPath() + "/" + (*it) + "/stickynotes_applet";
                  if (dir.exists(fullPath))
                        founds += fullPath;
            }
      }

      for ( QStringList::Iterator it = founds.begin(); it != founds.end(); ++it ) { // For each file
            QFile file(*it);
            QDomDocument *doc = XMLWork::openFile("stickynotes", *it);
            if (doc == 0)
                  continue;

            // First create a basket for it:
            QString basketFolder = BasketFactory::createBasketClips( i18n("Notes from Sticky Notes") );
            Basket *basket = loadBasket(basketFolder);
            basket->setIcon("gnome");
            basket->save(); // In case no item is added after that

            QDomElement docElem = doc->documentElement();
            for ( QDomNode n = docElem.firstChild(); !n.isNull(); n = n.nextSibling() ) {
                  QDomElement e = n.toElement();
                  if ( (!e.isNull()) && e.tagName() == "note" ) {
                        QString title = e.attribute("title");
                        QString font  = e.attribute("font");
                        QString body  = e.text();
                        int fontInt = 0;
                        if (font.contains("serif", false) || font.contains("roman", false))
                              fontInt = 2;
                        if (font.contains("sans", false) || // No "else if" because "sans serif" must
                            font.contains("arial", false) || font.contains("helvetica", false))
                              fontInt = 1;              // be counted as "sans". So, the order between "serif" and "sans" is important
                        if (font.contains("mono", false) || font.contains("courier", false) ||
                            font.contains("typewriter", false) || font.contains("console", false) ||
                            font.contains("terminal", false) || font.contains("news", false))
                              fontInt = 3;
                        Item *item = ItemFactory::createItemText(title, basket);
                        item->setTextStyle(item->textFontType(), QColor("#110099"));
                        Item *item2 = ItemFactory::createItemText(fromICS(body), basket);
                        item2->setTextStyle(fontInt, item2->textColor());
                        wasImported = true;
                  }
            }
      }
}

void Container::showHideSearchBar(bool show, bool switchFocus)
{
      if (show != m_actShowSearch->isChecked())
            m_actShowSearch->setChecked(show);

      currentDecoratedBasket()->setSearchBarShown(show, switchFocus);
      currentDecoratedBasket()->resetSearch();
}

01328 void Container::insertEmpty(int type)
{
      if (currentBasket()->isLocked()) {
            Global::mainContainer->showPassiveImpossible(i18n("Cannot add item."));
            return;
      }
      ItemFactory::insertEmpty(type, currentBasket());
}

void Container::insertWizard(int type)
{
      if (currentBasket()->isLocked()) {
            Global::mainContainer->showPassiveImpossible(i18n("Cannot add item."));
            return;
      }
      ItemFactory::insertWizard(type, currentBasket());
}

// BEGIN Color picker (code from KColorEdit):

/* Activate the mode
 */
void Container::slotColorFromScreen(bool global)
{
      m_colorPickWasGlobal = global;
      if (isActiveWindow()) {
            hide();
            m_colorPickWasShown = true;
      } else
            m_colorPickWasShown = false;

      m_colorPicker->pickColor();

/*    m_gettingColorFromScreen = true;
      kapp->processEvents();
      QTimer::singleShot( 100, this, SLOT(grabColorFromScreen()) );*/
}

void Container::slotColorFromScreenGlobal()
{
      slotColorFromScreen(true);
}

void Container::colorPicked(const QColor &color)
{
      Item *item = ItemFactory::createItemColor(color, currentBasket());
      currentBasket()->ensureVisibleItem(item);
      currentBasket()->unselectAllBut(item);
      currentBasket()->setFocusedItem(item);

      if (m_colorPickWasShown)
            show();

      if (m_colorPickWasGlobal && Settings::usePassivePopup())
            showPassiveDropped(i18n("Picked color to basket <i>%1</i>"), false);
}

/* When firered from basket context menu, and not from menu, grabMouse doesn't work!
 * It's perhapse because context menu call slotColorFromScreen() and then
 * ungrab the mouse (since menus grab the mouse).
 * But why isn't there such bug with normal menus?...
 * By calling this method with a QTimer::singleShot, we are sure context menu code is
 * finished and we can grab the mouse without loosing the grab:
 */
//void Container::grabColorFromScreen()
void Container::colorPickingCanceled()
{
      show();
/*    grabKeyboard();
      grabMouse(crossCursor);*/

      // From QT documentation:
      // " Note that only visible widgets can grab mouse input.
      //   If isVisible() returns FALSE for a widget, that widget cannot call grabMouse(). "
      // So, it's impossible to hide the window before grabbing the mouse, neither it's possible to use a global shortcut
}

/* Validate the color
 */
/*void Container::mouseReleaseEvent(QMouseEvent *event)
{
      if (m_gettingColorFromScreen) {
            m_gettingColorFromScreen = false;
            releaseMouse();
            releaseKeyboard();
            QColor color = KColorDialog::grabColor(event->globalPos());
            ItemFactory::createItemColor(color, currentBasket());
      } else
            KMainWindow::mouseReleaseEvent(event);
}*/

/* Cancel the mode
 */
/*void Container::keyPressEvent(QKeyEvent *event)
{
      if (m_gettingColorFromScreen)
            if (event->key() == Qt::Key_Escape) {
                  m_gettingColorFromScreen = false;
                  releaseMouse();
                  releaseKeyboard();
            }
      else
            KMainWindow::keyPressEvent(event);
}*/

// END Color picker


01436 void Container::toggleMenuBar()
{
      if (menuBar()->isVisible()) {
            int really = KMessageBox::questionYesNo(this,
                  i18n("<p>You are about to hide the menubar.</p><p>"
                       //"Press <b>Ctrl+M</b> to show the menubar again.<br>"
                       "To show the menubar again, right click the tabbar and "
                       "choose <b>Show Menubar</b> in the <b>Settings</b> submenu.</p>"),
                  i18n("Hidding Menubar"), KGuiItem(i18n("&Hide Menubar"), "showmenu"), KStdGuiItem::cancel(), "hideMenuBarInfo");
            if (really == KMessageBox::Yes)
                  menuBar()->hide();
            else
                  m_actShowMenubar->setChecked(true); // Re-check the option!
      } else
            menuBar()->show();

      saveMainWindowSettings( KGlobal::config(), autoSaveGroup() );
}

void Container::toggleToolBar()
{
      if (toolBar()->isVisible())
            toolBar()->hide();
      else
            toolBar()->show();

      saveMainWindowSettings( KGlobal::config(), autoSaveGroup() );
}

void Container::toggleStatusBar()
{
      if (statusBar()->isVisible())
            statusBar()->hide();
      else
            statusBar()->show();

      saveMainWindowSettings( KGlobal::config(), autoSaveGroup() );
}

void Container::configureToolbars()
{
      saveMainWindowSettings( KGlobal::config(), autoSaveGroup() );

      KEditToolbar dlg(actionCollection());
      connect( &dlg, SIGNAL(newToolbarConfig()), this, SLOT(slotNewToolbarConfig()) );
      dlg.exec();
}

void Container::configureNotifications()
{
      // TODO
      // KNotifyDialog *dialog = new KNotifyDialog(this, "KNotifyDialog", false);
      // dialog->show();
}

void Container::slotNewToolbarConfig() // This is called when OK or Apply is clicked
{
      // ...if you use any action list, use plugActionList on each here...
            createGUI();
            plugActionList( QString::fromLatin1("baskets_list"), actBasketsList);
      applyMainWindowSettings( KGlobal::config(), autoSaveGroup() );
}

01499 void Container::changeStatusbar(const QString& text)
{
    statusBar()->message(text);
}

void Container::postStatusbarMessage(const QString& text)
{
    statusBar()->message(text, 2000);
}

void Container::setStatusBarEditing()
{
      if (Settings::enterValidateInline())
            m_basketStatus->setText(i18n("Editing. Press Escape, Return or click outside to validate."));
      else
            m_basketStatus->setText(i18n("Editing. Press Escape or click outside to validate."));
}

void Container::setStatusBarDrag()
{
      m_basketStatus->setText(i18n("Ctrl+drop: copy, Shift+drop: move, Shift+Ctrl+drop: link."));
}

void Container::setStatusBarNormal()
{
      if (Global::clickCursorFeedback->feedbackedWidget() != 0L)
            return;

      QString basketStatus;
      if (currentBasket()->isAClipboard() && currentBasket()->isAStack())
            basketStatus = i18n("Clipboard stack basket.");
      else if (currentBasket()->isAClipboard())
            basketStatus = i18n("Clipboard basket.");
      else if (currentBasket()->isAStack())
            basketStatus = i18n("Stack basket."); // TODO: "Queue basket." ?
      else if (currentBasket()->isAMirror())
            basketStatus = i18n("Folder mirror basket.");
      else if (currentBasket()->showCheckBoxes())
            basketStatus = i18n("Checklist basket.");
      else
            basketStatus = i18n("Clips basket.");

      if (m_basketStatus->text() != basketStatus) // Avoid flicker
            m_basketStatus->setText(basketStatus);
}

void Container::setStatusBarHint(const QString &hint)
{
      if (m_basketStatus->text() != hint) // Avoid flicker
            m_basketStatus->setText(hint);
}

void Container::resetStatusBarHint()
{
      if (currentBasket()->isDuringEdit())
            setStatusBarEditing();
      else if (currentBasket()->isDuringDrag())
            setStatusBarDrag();
      else
            setStatusBarNormal();
}

void Container::feedbackShiftCursor(bool shiftPressed)
{
      OnClickAction::feedbackShiftCursor(shiftPressed);
}

void Container::stopHoverFeedbackBH() // BH for "Bottom Half" (like in Linux kernel ;-) )
{
      if (Global::clickCursorFeedback->feedbackedWidget() == 0L)
            Global::mainContainer->resetStatusBarHint();
}

01572 void Container::loadBaskets()
{
      QStringList failed;

/** Firstly load all previously openned baskets (including mirror ones) : */

      // TODO: Also store the last shown basket here ?

      QDomDocument *doc = XMLWork::openFile("container", Global::basketsFolder() + "container.baskets");
      if (doc != 0) {
            QDomElement docElem = doc->documentElement();
            QDomElement baskets = XMLWork::getElement(docElem, "baskets");

            QDomNode n = baskets.firstChild();
            while ( ! n.isNull() ) {
                  QDomElement e = n.toElement();
                  if ( (!e.isNull()) && e.tagName() == "basket" ) {
                        Basket *loaded = loadBasket(e.text(), false);
                        if (loaded == 0L)
                              failed.append(e.text());
                  }
                  n = n.nextSibling();
            }
      }

/** And then load the baskets in the Global::basketsFolder() that weren't loaded (import < 0.5.0 ones) */

      QDir dir(Global::basketsFolder(), QString::null,
               QDir::Name | QDir::IgnoreCase, QDir::Dirs | QDir::NoSymLinks);

      QStringList list = dir.entryList();
      bool wasImported = false;
      if ( list.count() > 2 )                                                     // Pass "." and ".."
            for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) // For each folder
                  if ( *it != "." && *it != ".." )                                    // If it can be a basket folder
                        if (basketForFolderName((*it) + "/") == 0) {                    // And folder not already loaded
                              if ( ! failed.contains((*it) + "/") ) {                     // And we not already tried to load it
                                    loadBasket( (*it) + "/", false );                       // Load it
                                    wasImported = true;                                     // Set the flag to say basket(s) was loaded
                              }
                        }

      if (wasImported)
            save();

      /*if ( ! failed.isEmpty() ) {
            KMessageBox::informationList( this,  / * TODO FIXME i18n* /QString(
                  "<p>The following baskets failed to load.</p>"
                  "<p>Please check if it exists, is readable and if data aren't corrupted.</p>"),
                  failed, / *i18n* /QString("Basket Load Failure") );
      / *   KMessageBox::error( this, / * TODO FIXME i18n* /QString(
                  "<p>The basket <b>%1</b> failed to load.</p>"
                  "<p>Please check if it exists, is readable and if data aren't corrupted.</p>").arg(basket->folderName()),
                  / *i18n* /QString("Basket Load Failure") );
      }*/

      if (listBaskets().count() == 0) // TODO: Create a basket of examples (tutorial) or link to a short help ?
            loadBasket( BasketFactory::createBasketClips() );

      m_tab->setCurrentPage(Settings::lastBasket());
      currentBasket()->setFocus();// At BasKet start, no widget have focus!
}

void Container::save()
{
      // Create document
      QDomDocument doc("container");
      QDomElement root = doc.createElement("container");
      doc.appendChild(root);

      // Create baskets element and populate it
      QDomElement baskets = doc.createElement("baskets");
      root.appendChild(baskets);

      QPtrList<Basket> basketsList = listBaskets();
      Basket *basket;
      for (basket = basketsList.first(); basket; basket = basketsList.next())
            XMLWork::addElement( doc, baskets, "basket", basket->folderName() );

      QFile file(Global::basketsFolder() + "container.baskets");
      if ( file.open(IO_WriteOnly) ) {
            QTextStream stream(&file);
            stream.setEncoding(QTextStream::UnicodeUTF8);
            QString xml = doc.toString();
            // FIXME: Actually use ISO-8859-15 because else, accentued characters in links are not kept :
            //stream << "<?xml version=\"1.0\" encoding=\"ISO-8859-15\"?>\n";
            stream << xml;
            file.close();
      }
}

Basket* Container::basketForFolderName(const QString &folderName)
{
      QPtrList<Basket> basketsList = listBaskets();
      Basket *basket;
      for (basket = basketsList.first(); basket; basket = basketsList.next())
            if (basket->folderName() == folderName)
                  return basket;

      return 0;
}

Basket* Container::basketAt(int index)
{
      return decoratedBasketAt(index)->basket();
}

DecoratedBasket* Container::decoratedBasketAt(int index)
{
      return (DecoratedBasket*)m_tab->page(index);
}

DecoratedBasket* Container::currentDecoratedBasket()
{
      return (DecoratedBasket*)m_tab->currentPage(); // currentBasket()->parent();
}

void Container::setSearching(bool searching)
{
      m_actResetSearch->setEnabled(searching);
}

void Container::showAppPurpose()
{
      QWhatsThis::display(i18n(
            "<p>BasKet let you to collect a wide variety of objects and keep them all in one place.</p>"
            "<p>You can group things for different purposes in tabs by creating as many new baskets as you want.<br>"
            "Items can be re-arranged, annotations can be associated to, and you can drag them back to other "
            "applications when needed.</p>"
            "<p>You can use baskets to take notes, clean up your desktop, replace your bookmarks, store links to "
            "applications you often use, or even create special baskets where items can be checked to make a shop-list, "
            "use baskets as stacks or create an advanced clipboard manager.</p>"));
}

void Container::slotDontShowEmptyHelp(bool dont)
{
      // Remember the setting:
      Settings::setShowEmptyBasketInfo(!dont);

      // And apply it to all baskets for consistency:
/*    QPtrList<Basket> baskets = listBaskets();
      for (uint i = 0; i < baskets.count(); ++i )
            baskets.at(i)->checkShowEmptyBasketInfo(dont);*/
}

01717 void Container::undo()
{
      // TODO
}

void Container::redo()
{
      // TODO
}

void Container::pasteToBasket(int index, QClipboard::Mode mode)
{
      basketAt(index)->pasteItem(mode);
}

void Container::contextMenu(int tabIndex, const QPoint &globalPos)
{
      QPopupMenu *menu;

      // If the context menu is about a tab / a basket
      if (tabIndex != -1) {
            setCurrentBasket(tabIndex); // A non beautiful hack for KActions to match the good basket....
            if (currentBasket()->isAStack())
                  menu = popupMenu("basket_stack_popup");
            else if (currentBasket()->isAMirror())
                  menu = popupMenu("basket_mirror_popup");
            else
                  menu = popupMenu("basket_popup");
      // Else, if the context menu is not about a tab / a basket : it's about the tab bar
      } else
            menu = popupMenu("tab_bar_popup");

      menu->exec(globalPos);
}

// FIXME: Duplicate code
void Container::contextMenu(int tabIndex, const QRect &globalRect)
{
      QPopupMenu *menu;

      // If the context menu is about a tab / a basket
      if (tabIndex != -1) {
            setCurrentBasket(tabIndex); // A non beautiful hack for KActions to match the good basket....
            if (currentBasket()->isAStack())
                  menu = popupMenu("basket_stack_popup");
            else if (currentBasket()->isAMirror())
                  menu = popupMenu("basket_mirror_popup");
            else
                  menu = popupMenu("basket_popup");
      // Else, if the context menu is not about a tab / a basket : it's about the tab bar
      } else
            menu = popupMenu("tab_bar_popup");

      PopupMenu::execAtRectBottom(*menu, globalRect);
}

void Container::propBasket(int index)
{
      m_contextIndex = index;   // FIXME: m_contextIndex is VERY VERY VERY uggly !
      propBasket();
}

void Container::propBasket()
{
      if ( basketAt(m_contextIndex)->isLocked() )
            return;

      BasketPropertiesDialog *bProp = new BasketPropertiesDialog(basketAt(m_contextIndex), this);
      bProp->exec(); // FIXME: delete bProp;

      tabChanged(0); // In case of change from/to "Clips basket." to/from "Stack basket."...
}

void Container::delBasket()
{
      DecoratedBasket *decoBasket    = currentDecoratedBasket();//decoratedBasketAt(m_contextIndex);
      Basket          *basket        = currentBasket();//basketAt(m_contextIndex);
      int              really;
      bool             delFolder;
      bool             delBasketData = true;

      if (basket->isAMirror()) {
            really = KMessageBox::questionYesNo( this,
                  i18n("<p>Do you really want to delete <b>%1</b>?</p>"
                       "<p>This basket mirror the contents of <b>%1</b>.<br>"
                       "The folder and its contents will not be removed.</p>")
                       .arg(Basket::textToHTMLWithoutP(basket->name())).arg(basket->folderName()),
                  i18n("Delete Basket") );
            delBasketData = KMessageBox::questionYesNo( this,
                  i18n("<p>Do you want to delete the basket data (stored in the mirrored folder)?</p>"
                       "<p>Those data save the layout and properties, but not the items themselves.<br>"
                       "If you don't plan to reload the basket later, you can safely delete the basket data.</p>"),
                  i18n("Delete Basket")
                  ) == KMessageBox::Yes; // Transform to bool
            delFolder = false;
      } else {
            really = KMessageBox::questionYesNo( this,
                  i18n("<qt>Do you really want to delete <b>%1</b> and its contents?</qt>")
                        .arg(Basket::textToHTMLWithoutP(basket->name())),
                  i18n("Delete Basket") );
            delFolder = true;
      }

      if (really == KMessageBox::No)
            return;

      if ( ! delFolder && delBasketData )
            basket->deleteBasketData();
      if (delFolder)
            basket->deleteFiles();

      m_tab->removePage(decoBasket);
      delete decoBasket;
//    delete basket;

      if (m_tab->count() == 0)
            loadBasket( BasketFactory::createBasketClips() ); // Will be saved...
      else
            save();      // ... So no need to save it twice

      basketNumberChanged();
      rebuildBasketsMenu();
}

void Container::lockBasket()
{
      Basket *cur = basketAt(m_contextIndex); // FIXME: m_contextIndex should be forgotten: Use currentBasket() instead

      cur->setLocked( ! cur->isLocked() );
      cur->save();

      Global::tray->updateToolTip();

      // Update displays :
      tabChanged(0);
}

void Container::showSettingsDialog()
{
      SettingsDialog *appS = new SettingsDialog(this);
      appS->exec();
      delete appS;
}

void Container::showShortcutsSettingsDialog()
{
      KKeyDialog::configure(actionCollection(), "basketui.rc");
      //.setCaption(..)
      //actionCollection()->writeSettings();
}

void Container::showGlobalShortcutsSettingsDialog()
{
      KKeyDialog::configure(Global::globalAccel);
      //.setCaption(..)
      Global::globalAccel->writeSettings();
}

void Container::changedSelectedItems()
{
      tabChanged(0); // FIXME: NOT OPTIMIZED
}

void Container::areSelectedItemsCheckedChanged(bool checked)
{
      m_actCheckItems->setChecked(checked && currentBasket()->showCheckBoxes());
}

void Container::basketNumberChanged()
{
      m_actPreviousBasket->setEnabled(m_tab->count() > 1);
      m_actNextBasket    ->setEnabled(m_tab->count() > 1);
}

void Container::currentBasketChanged()
{
}

void Container::isLockedChanged()
{
      bool isLocked = currentBasket()->isLocked();

      if (isLocked) {
            m_lockStatus->setPixmap(SmallIcon("encrypted.png"));
            QToolTip::add(m_lockStatus, i18n(
                  "<p>This basket is <b>locked</b>.<br>Click to unlock it.</p>").replace(" ", "&nbsp;") );
//          QToolTip::add(m_lockStatus, i18n("This basket is locked.\nClick to unlock it."));
      } else {
            m_lockStatus->clear();
            QToolTip::add(m_lockStatus, i18n(
                  "<p>This basket is <b>unlocked</b>.<br>Click to lock it.</p>").replace(" ", "&nbsp;") );
//          QToolTip::add(m_lockStatus, i18n("This basket is unlocked.\nClick to lock it."));
      }

      m_actLockBasket->setChecked(isLocked);
      m_actPropBasket->setEnabled(!isLocked);
      m_actDelBasket ->setEnabled(!isLocked);
      updateItemsActions();
}

void Container::countSelectedsChanged() // TODO: rename to countChanged() or itemsStateChanged()..;
{
      Basket *basket = currentBasket();

      // Update statusbar message :
      if (basket->count() == 0)
            m_selectionStatus->setText(i18n("No items"));
      else {
            QString count     = i18n("%n item",     "%n items",     basket->count()         );
            QString selecteds = i18n("%n selected", "%n selecteds", basket->countSelecteds());
            QString showns    = i18n("all shown");
            if (basket->countShown() != basket->count())
                  showns = i18n("%n found", "%n founds", basket->countShown());
            m_selectionStatus->setText(
                  i18n("e.g. \"18 items, 10 founds, 5 selecteds\"", "%1, %2, %3").arg(count).arg(showns).arg(selecteds) );
      }

      m_actClearStack ->setEnabled( basket->isAStack() && (basket->count() > 0) );

      bool enableCheckRelateds = basket->showCheckBoxes() && (basket->countShown() > 0);

      m_actSelectAll         ->setEnabled( basket->countSelecteds() < basket->countShown() );
      m_actUnselectAll       ->setEnabled( basket->countSelecteds() > 0                    );
      m_actInvertSelection   ->setEnabled( basket->countShown() > 0                        );
      m_actSelectCheckedItems->setEnabled( enableCheckRelateds                             );

      m_actPrevChecked  ->setEnabled(enableCheckRelateds); // TODO: countChecked() ;; countShown() ???
      m_actNextChecked  ->setEnabled(enableCheckRelateds);
      m_actPrevUnchecked->setEnabled(enableCheckRelateds); // TODO: count() - countChecked() ???
      m_actNextUnchecked->setEnabled(enableCheckRelateds);

      updateItemsActions();
}

void Container::updateItemsActions()
{
      bool isLocked             = currentBasket()->isLocked();
      bool oneSelected          = currentBasket()->countSelecteds() == 1;
      bool oneOrSeveralSelected = currentBasket()->countSelecteds() >= 1;

      // FIXME: m_actCheckItems is also modified in void Container::areSelectedItemsCheckedChanged(bool checked)
      //        bool Basket::areSelectedItemsChecked() should return false if bool Basket::showCheckBoxes() is false
      m_actCheckItems->setChecked( oneOrSeveralSelected &&
                                   currentBasket()->areSelectedItemsChecked() &&
                                   currentBasket()->showCheckBoxes()             );

      m_actEditItem        ->setEnabled( !isLocked && oneSelected          );
      m_actEditItemMetaData->setEnabled( !isLocked && oneSelected          );
      m_actCutItem         ->setEnabled( !isLocked && oneSelected          ); // TODO: oneOrSeveralSelected
      m_actCopyItem        ->setEnabled(              oneSelected          ); // TODO: oneOrSeveralSelected
      m_actPaste           ->setEnabled( !isLocked                         );
      m_actDelItem         ->setEnabled( !isLocked && oneOrSeveralSelected );
      m_actOpenItem        ->setEnabled(              oneOrSeveralSelected );
      m_actOpenItemWith    ->setEnabled(              oneSelected          ); // TODO: oneOrSeveralSelected IF SAME TYPE
      m_actSaveItemAs      ->setEnabled(              oneSelected          ); // IDEM?
      m_actCheckItems      ->setEnabled( !isLocked && oneOrSeveralSelected && currentBasket()->showCheckBoxes() );
      m_actMoveOnTop       ->setEnabled( !isLocked && oneOrSeveralSelected );
      m_actMoveItemUp      ->setEnabled( !isLocked && oneOrSeveralSelected );
      m_actMoveItemDown    ->setEnabled( !isLocked && oneOrSeveralSelected );
      m_actMoveOnBottom    ->setEnabled( !isLocked && oneOrSeveralSelected );

      for (KAction *action = m_insertActions.first(); action; action = m_insertActions.next())
            action->setEnabled( !isLocked );

      // From the old Item::contextMenuEvent(...) :
/*    if (useFile() || m_type == Link) {
            m_type == Link ? i18n("&Open target")         : i18n("&Open")
            m_type == Link ? i18n("Open target &with...") : i18n("Open &with...")
            m_type == Link ? i18n("&Save target as...")   : i18n("&Save a copy as...")
            // If useFile() theire is always a file to open / open with / save, but :
            if (m_type == Link) {
                  if (url().prettyURL().isEmpty() && runCommand().isEmpty())     // no URL nor runCommand :
                        popupMenu->setItemEnabled(7, false);                       //  no possible Open !
                  if (url().prettyURL().isEmpty())                               // no URL :
                        popupMenu->setItemEnabled(8, false);                       //  no possible Open with !
                  if (url().prettyURL().isEmpty() || url().path().endsWith("/")) // no URL or target a directory :
                        popupMenu->setItemEnabled(9, false);                       //  not possible to save target file
            }
      } else if (m_type != Color) {
            popupMenu->insertSeparator();
            popupMenu->insertItem( SmallIconSet("filesaveas"), i18n("&Save a copy as..."), this, SLOT(slotSaveAs()), 0, 10 );
      }*/
}

02001 void Container::askNewBasket()
{
      AddBasketWizard(this).exec();
}

02006 Basket* Container::loadBasket(const QString &folderName, bool save, bool showErrors)
{
      if (folderName.isEmpty())
            return 0L;

      DecoratedBasket *decoBasket = new DecoratedBasket(m_tab, folderName);
      Basket *basket = decoBasket->basket();

      if ( ! basket->successfulyLoaded() ) {
            if (showErrors)
                  KMessageBox::error( this, /* TODO FIXME i18n*/QString(
                        "<p>The basket <b>%1</b> failed to load.</p>"
                        "<p>Please check if it exists, is readable and if data aren't corrupted.</p>").arg(basket->fullPath()),
                        /*i18n*/QString("Basket Load Failure") );
            delete decoBasket;
            return 0L;
      }

      m_tab->addTab(decoBasket, basket->name());
      basketIconChanged(basket, basket->icon()); // Do not take pain to create an inconloader / iconset for addTab()
      m_tab->showPage(decoBasket);

      connect( basket, SIGNAL(nameChanged(Basket*, const QString&)), this, SLOT(basketNameChanged(Basket*, const QString&)) );
      connect( basket, SIGNAL(iconChanged(Basket*, const QString&)), this, SLOT(basketIconChanged(Basket*, const QString&)) );
      connect( basket, SIGNAL(changedSelectedItems()),               this, SLOT(changedSelectedItems())                     );
      connect( basket, SIGNAL(areSelectedItemsCheckedChanged(bool)), this, SLOT(areSelectedItemsCheckedChanged(bool))       );

      basketNumberChanged();
      rebuildBasketsMenu();

      if (save) // Save the list of baskets, whereas save is false (eg. during the load of each baskets)
            this->save();

      return basket;
}

// FIXME TODO: basketNameIconChanged(Basket *basket); !!

02044 void Container::basketNameChanged(Basket *basket, const QString &name)
{
      if ( Settings::onlyBasketsIcon() && ! basket->icon().isEmpty() )
            m_tab->setTabLabel( (QWidget*)basket->parent(), "" );
      else
            m_tab->setTabLabel( (QWidget*)basket->parent(), QString(name).replace("&", "&&") ); // Don't interprete '&'

      updateToolTips();
}

void Container::basketIconChanged(Basket *basket, const QString &icon)
{
      if ( ! icon.isEmpty() )
            m_tab->setTabIconSet( (QWidget*)basket->parent(), SmallIconSet(icon) );
      else
            m_tab->setTabIconSet( (QWidget*)basket->parent(), QIconSet() );

      // In case we have added/removed an icon, and the user want to
      //  show only the icons, the text must be hidden/shown :
      basketNameChanged(basket, basket->name());
}

void Container::updateTabs()
{
      for ( int i = 0; i < m_tab->count(); ++i ) {
            Basket *basket = basketAt(i);
            basketIconChanged( basket, basket->icon() ); // Name will be reloaded too
      }
}

void Container::updateToolTips()
{
      QStringList list;

      for ( int i = 0; i < m_tab->count(); ++i ) {
            Basket *basket = basketAt(i);
            if ( Settings::onlyBasketsIcon() && ! basket->icon().isEmpty() )
                  list.append(basket->name());
            else
                  list.append("");
      }

      m_tab->updateToolTips(list);
}

void Container::linkLookChanged()
{
      for ( int i = 0; i < m_tab->count(); ++i )
            basketAt(i)->linkLookChanged();
}

void Container::showItemsToolTipChanged()
{
      for ( int i = 0; i < m_tab->count(); ++i )
            basketAt(i)->showItemsToolTipChanged();
}

void Container::tabPlacementChanged(bool onTop)
{
      m_tab->setTabPosition( onTop ? QTabWidget::Top : QTabWidget::Bottom );
}

void Container::searchPlacementChanged(bool onTop)
{
      for ( int i = 0; i < m_tab->count(); ++i )
            decoratedBasketAt(i)->setSearchBarPosition(onTop);
}

02112 void Container::tabChanged(QWidget*)
{
      Settings::setLastBasket( m_tab->currentPageIndex() );
      m_contextIndex = m_tab->currentPageIndex(); // For the QAction to show Properties or lock basket

      // Update type of basket actions and statusbar
      resetStatusBarHint();

      setCaption( currentBasket()->name() );

      m_actOpenMirror  ->setEnabled(currentBasket()->isAMirror());
      //m_actReloadMirror->setEnabled(currentBasket()->isAMirror());

      isLockedChanged();       // Will also call updateItemsActions()
      countSelectedsChanged(); // Will also call updateItemsActions() : BAD (twice)

      m_actShowSearch->setChecked(currentBasket()->showSearchBar());

      if (Global::tray)
            Global::tray->updateToolTip();
}

02134 QPtrList<Basket> Container::listBaskets()
{
      QPtrList<Basket> list;

      // TODO: Optimize !
      for ( int i = 0; i < m_tab->count(); ++i )
            list.append( basketAt(i) );

      return list;
}

uint Container::currentBasketIndex()
{
      return m_tab->currentPageIndex();
}

Basket* Container::currentBasket()
{
      return currentDecoratedBasket()->basket();
}

void Container::setCurrentBasket(int index)
{
      m_tab->setCurrentPage(index);
      setActive(true);
}

void Container::changeBasketPlace(int index, int newIndex)
{
      DecoratedBasket *decoBasket = (DecoratedBasket*)m_tab->page(index);
      Basket          *basket     = decoBasket->basket();
      m_tab->removePage(decoBasket);
      m_tab->insertTab(decoBasket, basket->name(), newIndex); // TODO: insertBasket();
      basketIconChanged(basket, basket->icon()); // Do not take pain to create an inconloader / iconset for addTab()}
      setCurrentBasket(newIndex);
      rebuildBasketsMenu();
      save();
}

02173 void Container::setActive(bool active)
{
#if KDE_IS_VERSION( 3, 2, 90 )   // KDE 3.3.x
      if (active) {
            kapp->updateUserTimestamp(); // If "activate on mouse hovering systray", or "on drag throught systray"
            Global::tray->setActive();   //  FIXME: add this in the places it need
      } else
            Global::tray->setInactive();
#elif KDE_IS_VERSION( 3, 1, 90 ) // KDE 3.2.x
      // Code from Kopete (that seem to work, in waiting KSystemTray make puplic the toggleSHown) :
      if (active) {
            show();
            //raise() and show() should normaly deIconify the window. but it doesn't do here due
            // to a bug in QT or in KDE  (qt3.1.x or KDE 3.1.x) then, i have to call KWin's method
            if (isMinimized())
                  KWin::deIconifyWindow(winId());

            if ( ! KWin::windowInfo(winId(), NET::WMDesktop).onAllDesktops() )
                  KWin::setOnDesktop(winId(), KWin::currentDesktop());
            raise();
            // Code from me: expected and correct behavviour:
            kapp->updateUserTimestamp(); // If "activate on mouse hovering systray", or "on drag throught systray"
            KWin::activateWindow(winId());
      } else
            hide();
#else                            // KDE 3.1.x and lower
      if (active) {
            if (isMinimized())
                  hide();        // If minimized, show() doesn't work !
            show();            // Show it
            showNormal();      // If it was minimized
            raise();           // Raise it on top
            setActiveWindow(); // And set it the active window
      } else
            hide();
#endif
}

void Container::changeActive()
{
#if KDE_IS_VERSION( 3, 2, 90 ) // KDE 3.3.x
      kapp->updateUserTimestamp(); // If "activate on mouse hovering systray", or "on drag throught systray"
      Global::tray->toggleActive();
#else
      setActive( ! isActiveWindow() );
#endif
}

void Container::show()
{
      bool shouldSave = false;

      // If position and size has never been set, set nice ones:
      //  - Set size to sizeHint()
      //  - Keep the window manager placing the window where it want and save this
      if (Settings::mainWindowSize().isEmpty()) {
            resize(QSize(500,375)); // sizeHint() is bad (too small)
            shouldSave = true;
      } else {
            move(Settings::mainWindowPosition());
            resize(Settings::mainWindowSize());
      }

      KMainWindow::show();

      if (shouldSave) {
            Settings::setMainWindowPosition(pos());
            Settings::setMainWindowSize(size());
      }
}

void Container::resizeEvent(QResizeEvent*)
{
      Settings::setMainWindowSize(size());
}

void Container::moveEvent(QMoveEvent*)
{
      Settings::setMainWindowPosition(pos());
}

bool Container::askForQuit()
{
      QString message = i18n("<p>Do you really want to quit BasKet?</p>");
      if (Settings::useSystray())
            message += i18n("<p>Notice that you haven't to quit BasKet before ending you KDE session: "
                            "it will be reloaded the next time you log in.</p>");

      int really = KMessageBox::warningContinueCancel( this, message, i18n("Quit Confirm"),
            KStdGuiItem::quit(), "confirmQuitAsking" );

      if (really == KMessageBox::Cancel)
            return false;

      kapp->quit();
      return true;
}

bool Container::queryExit()
{
      hide();
      return true;
}

#include <qdesktopwidget.h>
#include <qmime.h>
#include <qpainter.h>
// To know the program name:
#include <kglobal.h>
#include <kinstance.h>
#include <kaboutdata.h>

bool Container::queryClose()
{
/*    if (m_shuttingDown) // Set in askForQuit(): we don't have to ask again
            return true;*/

      if (kapp->sessionSaving()) {
            Settings::setStartDocked(false); // If queryClose() is called it's because the window is shown
            return true;
      }

      if (Settings::useSystray()) {
            Global::tray->displayCloseMessage(i18n("Basket"));
            hide();
            return false;
      } else
            return askForQuit();
}

void Container::hideOnEscape()
{
      if (Settings::useSystray())
            setActive(false);
}

/** Scenario of "Hide main window to system tray icon when mouse move out of the window" :
  * - At enterEvent() we stop m_tryHideTimer
  * - After that and before next, we are SURE cursor is hovering window
  * - At leaveEvent() we restart m_tryHideTimer
  * - Every 'x' ms, timeoutTryHide() seek if cursor hover a widget of the application or not
  * - If yes, we musn't hide the window
  * - But if not, we start m_hideTimer to hide main window after a configured elapsed time
  * - timeoutTryHide() continue to be called and if cursor move again to one widget of the app, m_hideTimer is stopped
  * - If after the configured time cursor hasn't go back to a widget of the application, timeoutHide() is called
  * - It then hide the main window to systray icon
  * - When the user will show it, enterEvent() will be called the first time he enter mouse to it
  * - ...
  */

/** Why do as this ? Problems with the use of only enterEvent() and leaveEvent() :
  * - Resize window or hover titlebar isn't possible : leave/enterEvent
  *   are
  *   > Use the grip or Alt+rightDND to resize window
  *   > Use Alt+DND to move window
  * - Each menu trigger the leavEvent
  */

02331 void Container::enterEvent(QEvent*)
{
      m_tryHideTimer->stop();
      m_hideTimer->stop();
}

void Container::leaveEvent(QEvent*)
{
      if (Settings::useSystray() && Settings::hideOnMouseOut())
            m_tryHideTimer->start(50);
}

void Container::timeoutTryHide()
{
      // If a menu is displayed, do nothing for the moment
      if (kapp->activePopupWidget() != 0L)
            return;

      if (kapp->widgetAt(QCursor::pos()) != 0L)
            m_hideTimer->stop();
      else if ( ! m_hideTimer->isActive() ) // Start only one time
            m_hideTimer->start(Settings::timeToHideOnMouseOut() * 100, true);

      // If a sub-dialog is oppened, we musn't hide the main window:
      if (kapp->activeWindow() != 0L && kapp->activeWindow() != Global::mainContainer)
            m_hideTimer->stop();
}

void Container::timeoutHide()
{
      // We check that because the setting can have been set to off
      if (Settings::useSystray() && Settings::hideOnMouseOut())
            setActive(false);
      m_tryHideTimer->stop();
}

void Container::wheelEvent(QWheelEvent *event)
{
      int delta = (event->delta() < 0) - (event->delta() > 0); // 1 or -1
      int index = (m_tab->currentPageIndex() + delta) % m_tab->count();
      if (index < 0)
            index = m_tab->count() - 1;
      m_tab->setCurrentPage(index);

      if (Settings::usePassivePopup())
            showPassiveContent();

      event->accept();
}

void Container::rotateCurrentStack()
{
      currentBasket()->rotateStack();
}

void Container::insertStackItemInCurrentWindow()
{
      currentBasket()->insertStackItemInCurrentWindow();
}

void Container::pasteInCurrentBasket()
{
      currentBasket()->pasteItem();

      if (Settings::usePassivePopup())
            showPassiveDropped(i18n("Clipboard content (%1) pasted to basket <i>%2</i>"));
}

void Container::pasteSelInCurrentBasket()
{
      currentBasket()->pasteItem(QClipboard::Selection);

      if (Settings::usePassivePopup())
            showPassiveDropped(i18n("Selection (%1) pasted to basket <i>%2</i>"));
}

02407 void Container::goToPreviousBasket()
{
      int index = (m_tab->currentPageIndex() - 1);
      if (index < 0)
            index = m_tab->count() - 1;
      m_tab->setCurrentPage(index);
      if ( ! currentDecoratedBasket()->searchBar()->hasEditFocus() ) // Set focus to new current basket
            currentBasket()->setFocus();                               // But not if the search lineEdit was having focus

      if (Settings::usePassivePopup())
            showPassiveContent();
}

void Container::goToNextBasket()
{
      int index = (m_tab->currentPageIndex() + 1) % m_tab->count();
      m_tab->setCurrentPage(index);
      if ( ! currentDecoratedBasket()->searchBar()->hasEditFocus() ) // Set focus to new current basket
            currentBasket()->setFocus();                               // But not if the search lineEdit was having focus

      if (Settings::usePassivePopup())
            showPassiveContent();
}

02431 void Container::showPassiveDropped(const QString &title, bool showTypeName)
{
      if ( ! currentBasket()->isLocked() ) {
            m_passiveDroppedTitle         = title;
            m_passiveDroppedShortTypeName = showTypeName;
            QTimer::singleShot( c_delayTooltipTime, this, SLOT(showPassiveDroppedDelayed()) );
            // DELAY IT BELOW:
      } else
            showPassiveImpossible(i18n("No item was added."));
}

void Container::showPassiveDroppedDelayed()
{
      QString title        = m_passiveDroppedTitle;
      bool    showTypeName = m_passiveDroppedShortTypeName;

      delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time)
      m_passivePopup = new KPassivePopup(Settings::useSystray() ? (QWidget*)Global::tray : (QWidget*)Global::mainContainer);
      m_passivePopup->setView(
            (showTypeName ? title.arg(currentBasket()->lastInsertedItem()->typeName()) : title)
                 .arg(Basket::textToHTMLWithoutP(currentBasket()->name())),
            "<qt>" + currentBasket()->lastInsertedItem()->toHtml("_passivepopup_image_") + "</qt>",
            kapp->iconLoader()->loadIcon(currentBasket()->icon(), KIcon::NoGroup, 16, KIcon::DefaultState, 0L, true));
      m_passivePopup->show();
}

void Container::showPassiveImpossible(const QString &message)
{
      delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time)
      m_passivePopup = new KPassivePopup(Settings::useSystray() ? (QWidget*)Global::tray : (QWidget*)Global::mainContainer);
      m_passivePopup->setView(
            QString("<font color=red>%1</font>")
                  .arg(i18n("Basket <i>%1</i> is locked"))
                  .arg(Basket::textToHTMLWithoutP(currentBasket()->name())),
            message,
            kapp->iconLoader()->loadIcon(currentBasket()->icon(), KIcon::NoGroup, 16, KIcon::DefaultState, 0L, true));
      m_passivePopup->show();
}

void Container::showPassiveContent()
{
      // FIXME: Duplicate code (2 times)
      QString message;
      if (currentBasket()->canDragItem()) {
            Item *item = currentBasket()->currentStackItem();
            message = "<p>" + i18n("%1 item to drag (%2):")
                  .arg( currentBasket()->stackTakeAtEnd() ? i18n("Last") : i18n("First") )
                  .arg( item->typeName() ) + "<br>";
            message += item->toHtml("_passivepopup_image_");
      } else if (currentBasket()->isEmpty() && currentBasket()->isAStack())
            message = i18n("(Empty)");
      else
            message = "";

      delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time)
      m_passivePopup = new KPassivePopup(Settings::useSystray() ? (QWidget*)Global::tray : (QWidget*)Global::mainContainer);
      m_passivePopup->setView(
            "<qt>" + kapp->makeStdCaption( currentBasket()->isLocked()
                  ? QString("%1 <font color=gray30>%2</font>")
                        .arg(Basket::textToHTMLWithoutP(currentBasket()->name()), i18n("(Locked)"))
                  : Basket::textToHTMLWithoutP(currentBasket()->name()) ),
            message,
            kapp->iconLoader()->loadIcon(currentBasket()->icon(), KIcon::NoGroup, 16, KIcon::DefaultState, 0L, true));
      m_passivePopup->show();
}

#include "container.moc"

Generated by  Doxygen 1.6.0   Back to index