#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //WARNING: THIS IS NOT PORTABLE! // #include // #include #include #include #include #include // TO HERE -------- //#include "kdrawer.h" #include "baghiralinkdrag.h" #include "menu.h" #include "config.h" #include "help.h" #include "linkconfig.h" #define OPAQUE 0xffffffff #define OPACITY "_KDE_WM_WINDOW_OPACITY" #define _BIGSIZE_(_s_) ((_s_ == 16) ? 22 :\ (_s_ == 22) ? 32 :\ (_s_ == 32) ? 48 :\ (_s_ == 48) ? 64 :\ (_s_ == 64) ? 128 :\ (int)(_s_*1.4)) //TODO: sort functions alphabetically, split files by classes... refactoring sucks ;) static TQColor commentColor; static TQColor infoColor; static KConfig *config; static bool useKTTS; TQString spell(const TQString text) { TQString result; for (uint i = 0; i < text.length(); i++) { result += " "; result += text[i]; } return result; } /* Internal class to get access to protected TQBoxLayout-members */ class MyVBoxLayout : public TQVBoxLayout { friend class AppList; public: MyVBoxLayout( TQLayout * parentLayout, int spacing = -1, const char * name = 0 ) : TQVBoxLayout( parentLayout, spacing, name ) {} }; StartMenuButton::StartMenuButton( int size, TQString icon, TQString title, TQString command, Orientation orientation, TQWidget* parent, const char * name) : TQWidget(parent, name), m_title(title), m_command(command), m_icon(icon), m_orientation(orientation), _moving(false) { setBackgroundOrigin(TQWidget::ParentOrigin); int bigSize = _BIGSIZE_(size); m_pix = KGlobal::iconLoader()->loadIcon(icon, KIcon::Desktop, size); m_hoverPix = KGlobal::iconLoader()->loadIcon(icon, KIcon::Desktop, bigSize); m_pixmapLabel = new TQLabel(this, name); m_pixmapLabel->setPixmap(m_pix); m_pixmapLabel->setBackgroundOrigin(TQWidget::AncestorOrigin); TQBoxLayout* layout; if (orientation == Horizontal) { m_titleLabel = new TQLabel("" + title + "", this, name); m_titleLabel->setBackgroundOrigin(TQWidget::AncestorOrigin); m_titleLabel->setTextFormat( TQt::RichText ); m_titleLabel->setAlignment ( TQt::AlignLeft | TQt::AlignVCenter ); m_pixmapLabel->setFixedSize(bigSize+2,bigSize+2); m_pixmapLabel->setAlignment ( TQt::AlignCenter ); layout = new TQHBoxLayout ( this ); layout->addSpacing ( 5 ); layout->addWidget(m_pixmapLabel,0,TQt::AlignCenter); layout->addSpacing ( 2 ); layout->addWidget(m_titleLabel,1); layout->addSpacing ( 5 ); } else if (orientation == Vertical) { m_titleLabel = new TQLabel("" + title + "", this, name); m_titleLabel->setBackgroundOrigin(TQWidget::AncestorOrigin); m_titleLabel->setTextFormat( TQt::RichText ); m_titleLabel->setAlignment ( TQt::AlignHCenter | TQt::AlignTop ); m_pixmapLabel->setFixedSize(bigSize+2,bigSize+2); m_pixmapLabel->setAlignment ( TQt::AlignCenter ); layout = new TQVBoxLayout ( this ); layout->addSpacing ( 5 ); layout->addWidget(m_pixmapLabel,0,TQt::AlignCenter); layout->addSpacing ( 2 ); layout->addWidget(m_titleLabel,1); layout->addSpacing ( 5 ); } else { setFixedSize(bigSize+2,bigSize+2); m_pixmapLabel->setAlignment ( TQt::AlignCenter ); m_pixmapLabel->setFixedSize(bigSize+2,bigSize+2); } setCursor(TQt::PointingHandCursor); } void StartMenuButton::reloadIcon(int size) { int bigSize = _BIGSIZE_(size); if (m_orientation == Status) setFixedSize(bigSize+2,bigSize+2); m_pixmapLabel->setFixedSize(bigSize+2,bigSize+2); m_pix = KGlobal::iconLoader()->loadIcon(m_icon, KIcon::Desktop, size); m_hoverPix = KGlobal::iconLoader()->loadIcon(m_icon, KIcon::Desktop, bigSize); m_pixmapLabel->setPixmap(m_pix); } void StartMenuButton::smartMove(TQPoint &pt) { } void StartMenuButton::smartMove(int x, int y) { if (!dynamic_cast(parentWidget())) return; StartMenuButton *bt = 0L; TQObjectList *kids = const_cast(parentWidget()->children()); TQRect dRect(TQPoint(x,y), size()); TQRect bRect; if (kids && !kids->isEmpty()) { TQObject *o; for ( o = kids->first(); o; o = kids->next() ) if ((o != this) && (bt = (dynamic_cast(o)))) { bRect = TQRect(bt->pos(), bt->size()); if (dRect.intersects(bRect)) break; bt = 0L; } } if (!bt) { move(dRect.topLeft()); int dst; if (((Panel*)parentWidget())->orientation() == TQt::Horizontal) { dst = pos().x() + width() - parentWidget()->width(); if (dst > 0) emit updateSize(1); else if (pos().x() < 0) emit updateSize(-1); } else { dst = pos().y() + height() - parentWidget()->height(); if (dst > 0) emit updateSize(1); else if (pos().y() < 0) emit updateSize(-1); } ((Panel*)parentWidget())->ensureVisible(dRect); } else if ( // left of center of left (dRect.right() > bRect.right() && dRect.x() < bRect.right() - bRect.width() / 2) || // right of center of right (dRect.x() < bRect.x() && dRect.right() > bRect.x() + bRect.width() / 2) || // up of center of upper (dRect.bottom() > bRect.bottom() && dRect.y() < bRect.bottom() - bRect.height() / 2) || // below center of lower (dRect.y() < bRect.y() && dRect.bottom() > bRect.y() + bRect.height() / 2) ) { TQPoint bPt = bt->pos(); bt->move(pos()); move(bPt); } } void StartMenuButton::mouseReleaseEvent ( TQMouseEvent * mre) { if (mre->state() & TQt::LeftButton) { if (_moving) { _moving = false; return; } emit pressed(m_command); return; } if (mre->state() & TQt::RightButton) { if (!dynamic_cast(parentWidget())) return; ((Panel*)parentWidget())->linkConfigDialog->setCaption ( i18n("Configure Link") ); ((Panel*)parentWidget())->linkConfigDialog->title->setText(m_title); ((Panel*)parentWidget())->linkConfigDialog->command->setText(m_command); ((Panel*)parentWidget())->linkConfigDialog->icon->setIcon(m_icon); disconnect(((Panel*)parentWidget())->linkConfigDialog->buttonOk, SIGNAL(clicked()), 0, 0); connect(((Panel*)parentWidget())->linkConfigDialog->buttonOk, SIGNAL(clicked()), ((Panel*)parentWidget())->linkConfigDialog, SLOT(accept())); connect(((Panel*)parentWidget())->linkConfigDialog->buttonOk, SIGNAL(clicked()), this, SLOT(edit())); ((Panel*)parentWidget())->linkConfigDialog->exec(); } } void StartMenuButton::edit() { if (!dynamic_cast(parentWidget())) return; m_command = ((Panel*)parentWidget())->linkConfigDialog->command->text(); if (m_command.isEmpty()) { deleteLater(); return; } m_icon = ((Panel*)parentWidget())->linkConfigDialog->icon->icon(); m_title = ((Panel*)parentWidget())->linkConfigDialog->title->text(); int bigSize = _BIGSIZE_(((Panel*)parentWidget())->_size); m_pix = KGlobal::iconLoader()->loadIcon(m_icon, KIcon::Desktop, ((Panel*)parentWidget())->_size); m_hoverPix = KGlobal::iconLoader()->loadIcon(m_icon, KIcon::Desktop, bigSize); m_pixmapLabel->setPixmap(m_pix); if (m_orientation == Horizontal || m_orientation == Vertical) m_titleLabel->setText("" + m_title + ""); ((Panel*)parentWidget())->linkConfigDialog->close(); } void Panel::addIcon() { if (!linkConfigDialog->command->text().isEmpty()) addIcon ( linkConfigDialog->icon->icon(), linkConfigDialog->title->text(), linkConfigDialog->command->text(), iconAddPosition ); } void StartMenuButton::mouseMoveEvent ( TQMouseEvent * mme ) { if (!dynamic_cast(parentWidget())) return; if (mme->state() & TQt::LeftButton) { _moving = true; TQPoint pt = mapToParent(mme->pos()); if (!(mme->state() & TQt::ShiftButton)) { if (pt.y() < -5 || pt.y() > parentWidget()->height() + 5 || pt.x() < -5 || pt.x() > parentWidget()->width() + 5) { BaghiraLinkDrag *d = new BaghiraLinkDrag( m_title, m_command, m_icon, -1, parentWidget() ); d->setPixmap(m_hoverPix, TQPoint(m_hoverPix.width()/2, m_hoverPix.height()/2)); d->drag(); if ((mme->state() & TQt::ControlButton) || BaghiraLinkDrag::accepted()) return; ((Panel*)parentWidget())->poof(); // do NOT delete d. return; } } if (((Panel*)parentWidget())->orientation() == TQt::Horizontal) smartMove(pt.x() - width()/2, pos().y()); else smartMove(pos().x(), pt.y() - height()/2); } else _moving = false; } void StartMenuButton::enterEvent( TQEvent * ) { if (m_orientation == Status) emit hovered(m_title); m_pixmapLabel->setPixmap(m_hoverPix); } void StartMenuButton::leaveEvent( TQEvent * ) { if (m_orientation == Status) emit unhovered(); m_pixmapLabel->setPixmap(m_pix); } StartMenuEntry::StartMenuEntry(KService * service, TQString relPath, int size, bool newbie, TQWidget * parent) : TQWidget(parent) { groupPath = relPath; forNewbie = newbie; if (config) // might be first use ever... { TQString tmpString = config->readEntry(service->desktopEntryName()); if (tmpString != TQString::null) { usage = tmpString.section ( ' ', 0, 0 ).toUInt(); lastUse = TQDate::fromString(tmpString.section ( ' ', 1, 1 ), TQt::ISODate); // ranking is naiv but hopefully usefull for the beginning: often usage increases rank, time to the last usage decreases. "8" is just a "random" offset - the idea is that apps that have been used within the last week should have a higher rank than apps that don't appear in the list - setting these to - infinity isn't a good idea as well, as they might be brand new rank = 8 + usage - lastUse.daysTo(TQDate::currentDate()); } else { usage = 0; rank = 0; // neutral rank } } else { tqWarning("no valid config!"); usage = 0; rank = 0; // neutral rank } int bigSize = _BIGSIZE_(size); isCurrent = false; m_service = service; exec = m_service->exec(); display = false; m_pix = m_service->pixmap( KIcon::Desktop, size ); m_hoverPix = m_service->pixmap( KIcon::Desktop, bigSize ); m_titleLabel = new TQLabel("

" + m_service->name() + "

", this); m_titleLabel->setTextFormat( TQt::RichText ); m_commentLabel = new TQLabel(m_service->comment(), this); m_commentLabel->setPaletteForegroundColor(commentColor); m_commentLabel->setTextFormat( TQt::RichText ); m_pixmapLabel = new TQLabel(this); m_pixmapLabel->setFixedSize ( bigSize+2, bigSize+2 ); m_pixmapLabel->setAlignment(TQt::AlignCenter); m_pixmapLabel->setPixmap(m_pix); TQVBoxLayout* spacer = new TQVBoxLayout ( this ); spacer->addSpacing ( 1 ); TQHBoxLayout* layout = new TQHBoxLayout ( spacer ); layout->addWidget(m_pixmapLabel); layout->addSpacing ( 2 ); TQVBoxLayout* textLayout = new TQVBoxLayout ( layout ); layout->setStretchFactor ( textLayout, 1 ); textLayout->addWidget(m_titleLabel); textLayout->addWidget(m_commentLabel); layout->addStretch(); spacer->addSpacing ( 1 ); setCursor(TQt::PointingHandCursor); } void StartMenuEntry::reloadIcon(int size) { int bigSize = _BIGSIZE_(size); m_pixmapLabel->setFixedSize(bigSize+2,bigSize+2); m_pix = m_service->pixmap( KIcon::Desktop, size ); m_hoverPix = m_service->pixmap( KIcon::Desktop, bigSize ); m_pixmapLabel->setPixmap(m_pix); } StartMenuEntry::~StartMenuEntry() { // if (m_service) delete m_service; m_service = 0L; } void StartMenuEntry::saveStats() { if (usage > 0) config->writeEntry(m_service->desktopEntryName(), TQString::number(usage) + " " + lastUse.toString(TQt::ISODate)); } bool StartMenuEntry::operator==( const StartMenuEntry& se ) const { return rank == se.rank; } bool StartMenuEntry::operator!=( const StartMenuEntry& se ) const { return rank != se.rank; } bool StartMenuEntry::operator<( const StartMenuEntry& se ) const { /* if (rank == se.rank) return m_titleLabel->text() < se.title(); else */ return rank > se.rank; // to have descending sort order (we could also use a negative ranking...) } bool StartMenuEntry::operator>( const StartMenuEntry& se ) const { /* if (rank == se.rank) return m_titleLabel->text() > se.title(); else */ return rank < se.rank; // to have descending sort order (we could also use a negative ranking...) } bool StartMenuEntry::operator==( const double& d ) const { return rank == d; } bool StartMenuEntry::operator!=( const double& d ) const { return rank != d; } bool StartMenuEntry::operator<( const double& d ) const { return rank > d; // to have descending sort order (we could also use a negative ranking...) } bool StartMenuEntry::operator>( const double& d ) const { return rank < d; // to have descending sort order (we could also use a negative ranking...) } void StartMenuEntry::mouseReleaseEvent ( TQMouseEvent * e ) //TODO: do funny stuff with other buttons (e.g. provide edit dialog) { if (e->button() == TQt::LeftButton) { m_pixmapLabel->setPixmap(m_pix); execute(); if (!(e->state() & TQt::ControlButton)) emit pressed(); } if (e->button() == TQt::RightButton) { emit popup(this); } } void StartMenuEntry::mouseMoveEvent ( TQMouseEvent * mme ) { if (mme->state() & TQt::LeftButton && (mme->pos().y() < 0 || mme->pos().y() > height() || mme->pos().x() < 0 || mme->pos().x() > width())) { BaghiraLinkDrag *d = new BaghiraLinkDrag( m_service->name(), m_service->exec(), m_service->icon(), -1, parentWidget() ); d->setPixmap(m_hoverPix, TQPoint(m_hoverPix.width()/2, m_hoverPix.height()/2)); d->dragCopy(); // do NOT delete d. } } void StartMenuEntry::keyPressEvent ( TQKeyEvent * e ) { switch (e->key()) { case TQt::Key_Escape: emit closeMenu(); break; case TQt::Key_Return: case TQt::Key_Enter: execute(); if (!(e->state() & TQt::ControlButton)) emit pressed(); break; case TQt::Key_Down: emit appDown(); break; case TQt::Key_Up: emit appUp(); break; case TQt::Key_Home: // ->searchline + select case TQt::Key_Left: emit appLeft(); break; default: break; } } TQString StartMenuEntry::title() { return m_titleLabel->text(); } void StartMenuEntry::focusInEvent ( TQFocusEvent * ) { isCurrent = true; emit hovered("[ " + groupPath + " ] " + exec); if (useKTTS) { TQString text = i18n("for TTS output, telling which item is focussed (keyboard) and than reads the comment", "%1 focussed. %2").arg(m_titleLabel->text()).arg(m_commentLabel->text()); emit sayText(text); } setPaletteBackgroundColor(KGlobalSettings::highlightColor()); m_commentLabel->setPaletteBackgroundColor(KGlobalSettings::highlightColor()); setPaletteForegroundColor(KGlobalSettings::highlightedTextColor()); m_commentLabel->setPaletteForegroundColor(KGlobalSettings::highlightedTextColor()); } void StartMenuEntry::focusOutEvent ( TQFocusEvent * ) { emit unhovered(); isCurrent = false; setPaletteBackgroundColor(KGlobalSettings::baseColor()); m_commentLabel->setPaletteBackgroundColor(KGlobalSettings::baseColor()); if (hasMouse()) { setPaletteForegroundColor(KGlobalSettings::highlightColor()); m_commentLabel->setPaletteForegroundColor(KGlobalSettings::highlightColor()); } else { setPaletteForegroundColor(KGlobalSettings::textColor()); m_commentLabel->setPaletteForegroundColor(commentColor); } } void StartMenuEntry::enterEvent( TQEvent * ) { emit hovered("[ " + groupPath + " ] " + exec); if (useKTTS) { TQString text = i18n("for TTS output, telling which item is hovered (mouse) and than reads the comment", "%1 hovered. %2").arg(m_titleLabel->text()).arg(m_commentLabel->text()); emit sayText(text); } if (!isCurrent) { setPaletteForegroundColor(KGlobalSettings::highlightColor()); m_commentLabel->setPaletteForegroundColor(KGlobalSettings::highlightColor()); } m_pixmapLabel->setPixmap(m_hoverPix); } void StartMenuEntry::leaveEvent( TQEvent * ) { emit unhovered(); if (!isCurrent) { setPaletteForegroundColor(KGlobalSettings::textColor()); m_commentLabel->setPaletteForegroundColor(commentColor); } m_pixmapLabel->setPixmap(m_pix); } void StartMenuEntry::execute() { usage++; lastUse = TQDate::currentDate(); rank = 8 + usage; KApplication::startServiceByDesktopPath(m_service->desktopEntryPath(), TQStringList(), 0, 0, 0, "", true); emit executed(); } Panel::Panel(int size, TQWidget * parent, const char * name) : TQWidget(parent, name), _size(size), _draggedMe(false), _count(0), _orientation(TQt::Horizontal), _poof(0), _poofIndex(0), _poofAnimPix(0), _poofPix(0) { linkConfigDialog = new LinkConfig(); setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed); // setPaletteBackgroundColor(KGlobalSettings::highlightColor()); setAcceptDrops(true); config->setGroup("Panel"); TQStringList commands = config->readListEntry("Commands", '§'); TQStringList icons = config->readListEntry("Icons", '§'); TQStringList offsets = config->readListEntry("Offsets", '§'); TQStringList titles = config->readListEntry("Titles", '§'); TQStringList::Iterator it1 = commands.begin(); TQStringList::Iterator it2 = icons.begin(); TQStringList::Iterator it3 = offsets.begin(); TQStringList::Iterator it4 = titles.begin(); while (it1 != commands.end() && it2 != icons.end() && it3 != offsets.end() && it4 != titles.end()) { addIcon(*it2, *it4, *it1, TQPoint((*it3).toInt(),0)); ++it1; ++it2; ++it3; ++it4; } } void Panel::save(KConfig *config) { config->setGroup("Panel"); TQObjectList *kids = const_cast(children()); StartMenuButton *bt = 0; if (kids && !kids->isEmpty()) { TQStringList icons; TQStringList titles; TQStringList commands; TQStringList offsets; TQObject *o; for ( o = kids->first(); o; o = kids->next() ) if (bt = (dynamic_cast(o))) { icons.append(bt->icon()); titles.append(bt->title()); commands.append(bt->command()); _orientation == TQt::Horizontal ? offsets.append(TQString::number(bt->x())) : offsets.append(TQString::number(bt->y())); } config->writeEntry("Commands", commands, '§'); config->writeEntry("Icons", icons, '§'); config->writeEntry("Offsets", offsets, '§'); config->writeEntry("Titles", titles, '§'); } } void Panel::reloadIcons( int size) { _size = size; if (_orientation == TQt::Horizontal) { setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed); setFixedHeight(_BIGSIZE_(_size)+4); setMaximumWidth(32767); } else { setSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Expanding); setFixedWidth(_BIGSIZE_(_size)+4); setMaximumHeight(32767); } TQObjectList *kids = const_cast(children()); StartMenuButton *bt = 0; if (kids && !kids->isEmpty()) { TQObject *o; for ( o = kids->first(); o; o = kids->next() ) if (bt = (dynamic_cast(o))) { bt->reloadIcon(size); } } } void Panel::ensureVisible(TQRect & rect) { int dx = 0; int dy = 0; if (rect.width() > clipRegion().boundingRect().width()) dx = (rect.width() - clipRegion().boundingRect().width())/2 - rect.x(); else if (rect.right() > clipRegion().boundingRect().right()) dx = clipRegion().boundingRect().right() - rect.right(); else if (rect.x() < clipRegion().boundingRect().x()) dx = clipRegion().boundingRect().x() - rect.x(); if (rect.height() > clipRegion().boundingRect().height()) dy = (rect.height() - clipRegion().boundingRect().height())/2 - rect.y(); else if (rect.bottom() > clipRegion().boundingRect().bottom()) dy = clipRegion().boundingRect().bottom() - rect.bottom(); else if (rect.y() < clipRegion().boundingRect().y()) dy = clipRegion().boundingRect().y() - rect.y(); scroll(dx, dy); } void Panel::updateSize(int dst) { if (dst > 0) { if (_orientation == TQt::Horizontal) { resize(width()+dst, height()); } else { resize(width(), height()+dst); } } else // more complex: resize and reposition all children, so first one is on (0,0) { TQObjectList *kids = const_cast(children()); if (kids && !kids->isEmpty()) { TQObject *o; StartMenuButton *bt; if (_orientation == TQt::Horizontal) { resize(width()-dst, height()); for ( o = kids->first(); o; o = kids->next() ) if (bt = (dynamic_cast(o))) bt->move(TQPoint(bt->x()-dst, bt->y())); } else { resize(width(), height()-dst); for ( o = kids->first(); o; o = kids->next() ) if (bt = (dynamic_cast(o))) bt->move(TQPoint(bt->x(), bt->y()-dst)); } } } } void Panel::wheelEvent ( TQWheelEvent * we ) { if (_orientation == TQt::Vertical) { if (we->delta() > 0) { if (childrenRect().y() < clipRegion().boundingRect().y()) { if (childrenRect().y() + we->delta() < clipRegion().boundingRect().y()) scroll ( 0, we->delta() ); else scroll ( 0, clipRegion().boundingRect().y() - childrenRect().y() ); } } else { if (childrenRect().bottom() > clipRegion().boundingRect().bottom()) { if (childrenRect().bottom() + we->delta() > clipRegion().boundingRect().bottom()) scroll ( 0, we->delta() ); else scroll ( 0, clipRegion().boundingRect().bottom() - childrenRect().bottom() ); } } } else { if (we->delta() > 0) { if (childrenRect().x() < clipRegion().boundingRect().x()) { if (childrenRect().x() + we->delta() < clipRegion().boundingRect().x()) scroll ( we->delta(), 0 ); else scroll ( clipRegion().boundingRect().x() - childrenRect().x(), 0 ); } } else { if (childrenRect().right() > clipRegion().boundingRect().right()) { if (childrenRect().right() + we->delta() > clipRegion().boundingRect().right()) scroll ( we->delta(), 0 ); else scroll ( clipRegion().boundingRect().right() - childrenRect().right(), 0 ); } } } } void Panel::resizeEvent ( TQResizeEvent * e) { if (_orientation == TQt::Horizontal) { if (e->size().height() != e->oldSize().height()) { int h = e->size().height(); KPixmap bgPix = TQPixmap(32, h); KPixmap bgPix1 = TQPixmap(32, h/2); KPixmap bgPix2 = TQPixmap(32, h - bgPix1.height()); TQColor color = palette().color(TQPalette::Active, TQColorGroup::Background); KPixmapEffect::gradient( bgPix1, color.light(130), color.dark(105), KPixmapEffect::VerticalGradient, 0); KPixmapEffect::gradient( bgPix2, color.dark(120), color.light(110), KPixmapEffect::VerticalGradient, 0); TQPainter p(&bgPix); p.drawPixmap(0,0,bgPix1); p.drawPixmap(0,bgPix1.height(),bgPix2); p.end(); setPaletteBackgroundPixmap( bgPix ); } } else if (_orientation == TQt::Vertical) { if (e->size().width() != e->oldSize().width()) { int w = e->size().width(); KPixmap bgPix = TQPixmap(w, 32); KPixmap bgPix1 = TQPixmap(w/2, 32); KPixmap bgPix2 = TQPixmap(w - bgPix1.width(), 32); TQColor color = palette().color(TQPalette::Active, TQColorGroup::Background); KPixmapEffect::gradient( bgPix1, color.light(110), color.dark(120), KPixmapEffect::HorizontalGradient, 0); KPixmapEffect::gradient( bgPix2, color.dark(105), color.light(130), KPixmapEffect::HorizontalGradient, 0); TQPainter p(&bgPix); p.drawPixmap(0,0,bgPix1); p.drawPixmap(bgPix1.width(),0,bgPix2); p.end(); setPaletteBackgroundPixmap( bgPix ); } } TQWidget::resizeEvent( e ); } void Panel::poof() { /*if (_draggedMe) { _draggedMe = false; return; }*/ TQObjectList *kids = const_cast(children()); if (kids && !kids->isEmpty()) { TQObject *o; StartMenuButton *bt = 0L; for ( o = kids->first(); o; o = kids->next() ) { bt = 0L; if ((bt = (dynamic_cast(o))) && bt->isMoving()) { bt->hide(); bt->deleteLater(); bt = 0L; --_count; } } _poofIndex = 0; _poofPix = new TQPixmap(locateLocal("data", "baghira/poof.png"), "png"); _poofAnimPix = new TQPixmap(_poofPix->width(), _poofPix->width()); if (!_poof) _poof = new TQWidget(0,0, TQt::WType_TopLevel | TQt::WStyle_NoBorder | TQt::WStyle_StaysOnTop | TQt::WX11BypassWM); #if KDE_IS_VERSION(3,3,91) //3.4 beta KWin::setShadowSize(_poof->winId(), 0); #endif _poof->setFixedSize(_poofPix->width(), _poofPix->width()); int x = TQCursor::pos().x() - _poof->width()/2; int y = TQCursor::pos().y() - _poof->height()/2; TQPixmap bgPix = TQPixmap::grabWindow( tqt_xrootwin(), x, y, _poofPix->width(), _poofPix->width()); _poof->move(x,y); _poof->show(); _poof->setBackgroundOrigin(TQWidget::WidgetOrigin); _poof->setPaletteBackgroundPixmap( bgPix ); runPoof(); } } void Panel::runPoof() { if (_poofIndex > 4) { _poof->hide(); delete _poofPix; _poofPix = 0L; // delete _poof; // _poof = 0L; delete _poofAnimPix; _poofAnimPix = 0L; _poofIndex = 0; return; } _poof->erase(); bitBlt(_poof, 0 ,0, _poofPix, 0, _poofIndex * _poofPix->width(), _poofPix->width(), _poofPix->width(), TQt::AndROP); ++_poofIndex; TQTimer::singleShot ( 70, this, SLOT(runPoof()) ); // around 15 fps } void Panel::mouseReleaseEvent ( TQMouseEvent * mre ) { if (mre->state() & TQt::RightButton) { iconAddPosition = mre->pos(); linkConfigDialog->setCaption ( i18n("New Link") ); linkConfigDialog->title->clear(); linkConfigDialog->command->clear(); linkConfigDialog->icon->resetIcon(); disconnect(linkConfigDialog->buttonOk, SIGNAL(clicked()), 0, 0); connect(linkConfigDialog->buttonOk, SIGNAL(clicked()), linkConfigDialog, SLOT(accept())); connect(linkConfigDialog->buttonOk, SIGNAL(clicked()), this, SLOT(addIcon())); linkConfigDialog->exec(); } } void Panel::dragEnterEvent ( TQDragEnterEvent *dee ) { if (BaghiraLinkDrag::canDecode(dee)) { TQObjectList *kids = const_cast(children()); if (kids && !kids->isEmpty()) { TQObject *o; StartMenuButton *bt = 0L; for ( o = kids->first(); o; o = kids->next() ) if ((bt = (dynamic_cast(o))) && bt->isMoving()) // this is just some icon the user drags around ad that accidently left the panel { BaghiraLinkDrag::setAccepted(); // as we cannot access TQts dragmanager and qdragobject doesn't provide a function to cancel the drag, we just emit a virtual escape key... _draggedMe = true; // ensure to please not poof ;P XTestFakeKeyEvent(tqt_xdisplay(),XKeysymToKeycode(tqt_xdisplay(), XK_Escape), true, 0); XTestFakeKeyEvent(tqt_xdisplay(),XKeysymToKeycode(tqt_xdisplay(), XK_Escape), false, 0); XFlush(tqt_xdisplay()); repositionIcon(bt, mapFromGlobal(dee->pos())); return; } } dee->accept(TRUE); } else if (TQUriDrag::canDecode(dee) || TQTextDrag::canDecode(dee)) dee->accept(TRUE); } void Panel::dropEvent ( TQDropEvent *de ) { TQStrList list; TQString title; TQString command; TQString icon; int index; if ( BaghiraLinkDrag::decode(de, &title, &command, &icon, &index) ) { addIcon ( icon, title, command, TQPoint(de->pos().x() - (_BIGSIZE_(_size)/2), de->pos().y() - (_BIGSIZE_(_size)/2))); BaghiraLinkDrag::setAccepted(); } else if ( TQUriDrag::decode(de, list) ) { char *uri; KURL url; for ( uri = list.first(); uri; uri = list.next() ) { url = KURL(uri); if (url.protocol() == "http") addIcon ( "html", url.host()+(url.path()=="/"?TQString(""):url.path()), uri, de->pos() ); else { KFileItem item = KFileItem(KFileItem::Unknown, KFileItem::Unknown, url, true); addIcon ( item.iconName(), url.fileName().isEmpty()?url.prettyURL():url.fileName(), uri, de->pos() ); } } } else if (TQTextDrag::decode(de, command)) { KURL url(command); if (url.isValid()) { if (url.protocol() == "http") addIcon ( "html", url.host()+(url.path()=="/"?TQString(""):url.path()), command, de->pos() ); else { KFileItem item = KFileItem(KFileItem::Unknown, KFileItem::Unknown, url, true); addIcon ( item.iconName(), url.fileName().isEmpty()?url.prettyURL():url.fileName(), command, de->pos() ); } } else if (command.contains('@')) { command.replace(" ",""); addIcon ( "kmail", command, "mailto:"+command, de->pos() ); } else if (command.contains("'at'")) //last chance for anti-spam addy { command.replace(" ",""); command.replace("'at'","@"); addIcon ( "kmail", command, "mailto:"+command, de->pos() ); } else // ok, just take this as siple unknown command and hope the user knows, what she's ;) doing... { StartMenuButton *bt = addIcon ( command, command, command, de->pos() ); } } } void Panel::repositionIcon(StartMenuButton *button, TQPoint pt) { TQObjectList *kids = const_cast(children()); if (!kids || kids->isEmpty()) // the easy one ;) return; if (kids->count() == 1) // button's for certain the only child ;) { if (_orientation == TQt::Horizontal) button->move(pt.x(),0); else button->move(0,pt.y()); return; } TQObject *o; StartMenuButton *bt = 0L; int xy = 0; if (_orientation == TQt::Horizontal) { if (pt.x() < 0) // append horizontally { for ( o = kids->first(); o; o = kids->next() ) if ((bt = dynamic_cast(o)) && bt != button && bt->x() + bt->width() > xy ) xy = bt->x() + bt->width(); button->move(xy,0); } else // inject horizontally { // first find possible icon under the position for ( o = kids->first(); o; o = kids->next() ) { if ((bt = dynamic_cast(o)) && TQRect(bt->pos(), bt->size()).contains(pt)) break; else bt = 0l; } if (bt) // found? - decide whether to insert left or right { if (bt->x() + bt->width()/2 > pt.x()) // move to old icon place { button->move(bt->x(), 0); } else // move to right { button->move(bt->x() + bt->width(), 0); } // adjust right icons for ( o = kids->first(); o; o = kids->next() ) if ((bt = dynamic_cast(o)) && bt->x() >= button->x() && bt != button ) { bt->move(bt->x() + button->width(), 0); } } else // no collision, just move there button->move(pt.x(), 0); } } else { if (pt.y() < 0) // append vertically { for ( o = kids->first(); o; o = kids->next() ) if ((bt = dynamic_cast(o)) && bt != button && bt->y() + bt->height() > xy ) xy = bt->y() + bt->height(); button->move(0, xy); } else // inject vertically { // first find possible icon under the position for ( o = kids->first(); o; o = kids->next() ) { if ((bt = dynamic_cast(o)) && TQRect(bt->pos(), bt->size()).contains(pt)) break; else bt = 0l; } if (bt) // found? - decide whether to insert up or down { if (bt->y() + bt->height()/2 > pt.y()) // move to old icon place button->move(0, bt->y()); else // move to right button->move(0, bt->y() + bt->height()); // adjust lower icons for ( o = kids->first(); o; o = kids->next() ) if ((bt = dynamic_cast(o)) && bt->y() >= button->y() && bt != button ) bt->move(0, bt->y() + button->height()); } else // no collision, just move there button->move(0, pt.y()); } } } StartMenuButton* Panel::addIcon ( TQString icon, TQString title, TQString command, TQPoint pt ) { StartMenuButton *tmpButton = new StartMenuButton(_size, icon, title, command, StartMenuButton::Status, this); // reposition icon repositionIcon(tmpButton, pt); // connections connect (tmpButton, SIGNAL(hovered(const TQString &)), this, SIGNAL(message(const TQString &))); connect (tmpButton, SIGNAL(unhovered()), this, SIGNAL(clearStatus())); connect (tmpButton, SIGNAL(updateSize(int)), this, SLOT(updateSize(int))); connect (tmpButton, SIGNAL(pressed(const TQString &)), parent(), SLOT(execute(const TQString &))); connect (tmpButton, SIGNAL(pressed(const TQString &)), parent(), SLOT(close())); // done // inc counter _count++; tmpButton->show(); return tmpButton; } void Panel::setOrientation ( Orientation ori ) { if (_orientation == ori) return; _orientation = ori; TQObjectList *kids = const_cast(children()); if (!kids || kids->isEmpty()) return; TQObject *o; StartMenuButton *bt = 0L; for ( o = kids->first(); o; o = kids->next() ) if (bt = (dynamic_cast(o))) bt->move(TQPoint(bt->pos().y(), bt->pos().x())); } AppList::AppList(int size, TQWidget * parent) : TQScrollView(parent), _size(size) { popupBlocked_ = false; enableClipper( true ); setFrameStyle(TQFrame::LineEditPanel | TQFrame::Sunken ); configDialog_ = new ConfigDialog; helpDialog_ = new HelpDialog; connect (((TQObject*)configDialog_->buttonHelp), SIGNAL(clicked()), ((TQObject*)helpDialog_), SLOT(exec())); connect (((TQObject*)configDialog_->buttonCancel), SIGNAL(clicked()), this, SLOT(unblockPopup())); m_widget = new TQFrame(viewport()); m_widget->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum); m_widget->setPaletteBackgroundColor(KGlobalSettings::baseColor()); addChild(m_widget,0,0); setResizePolicy(TQScrollView::AutoOneFit); m_widget->show(); infoLayout = new TQVBoxLayout(m_widget); infoLabel = new TQLabel(m_widget); infoLabel->setPaletteBackgroundColor(infoColor); infoLabel->setTextFormat( TQt::RichText ); infoLayout->addWidget(infoLabel); m_VLayout = new TQVBoxLayout(infoLayout); m_iconLoader = KGlobal::iconLoader(); m_popup = new KPopupMenu(this); m_popup->insertItem(i18n("Edit Entry"), this, SLOT(editDialog())); m_popup->insertItem(i18n("Remove Entry"), this, SLOT(removeEntry())); m_popup->insertSeparator(); m_popup->insertItem(i18n("Add Entry"), this, SLOT(addDialog())); init(); } void AppList::mouseReleaseEvent ( TQMouseEvent * e ) { if (e->button() == TQt::RightButton) addDialog(); } void AppList::windowActivationChange ( bool oldActive ) { if (isActiveWindow() && entryList.current()) entryList.current()->setFocus(); TQScrollView::windowActivationChange ( oldActive ); } void AppList::reloadIcons( int size) { _size = size; TQPtrListIterator it(entryList); StartMenuEntry *runner; while( (runner = it.current()) != 0 ) { ++it; runner->reloadIcon(size); } } void AppList::addDialog() { disconnect (((TQObject*)configDialog_->buttonOk), SIGNAL(clicked()), this, 0); connect (((TQObject*)configDialog_->buttonOk), SIGNAL(clicked()), this, SLOT(addEntry())); configDialog_->appName->clear(); configDialog_->category->clearEdit(); configDialog_->command->clear(); configDialog_->genericName->clear(); configDialog_->iconButton->resetIcon(); configDialog_->keywords->clear(); configDialog_->startupFeedback->setChecked( true ); configDialog_->showInSystray->setChecked( false ); configDialog_->description->clear(); configDialog_->startInTerminal->setChecked( false ); configDialog_->terminalSettings->clear(); configDialog_->startAsUser->setChecked( false ); configDialog_->username->clear(); configDialog_->workingDir->clear(); configDialog_->shortcut->setShortcut(KShortcut::null(), false); configDialog_->setCaption ( i18n("New Entry") ); ((TQWidget*)(configDialog_->extendedGroup))->hide(); configDialog_->buttonDetail->setDown ( false ); configDialog_->adjustSize(); configDialog_->show(); } void AppList::addEntry() { TQString fullpath = configDialog_->category->currentText(); while (fullpath[0] == '/') // remove leading "/"'s { fullpath.remove(0,1); } fullpath = KService::newServicePath(true, fullpath + configDialog_->appName->text()); //tqWarning("%s",fullpath.ascii()); writeEntry(fullpath); KService *s = new KService(fullpath); TQStringList list(KServiceGroup::group(configDialog_->category->currentText())->caption()); StartMenuEntry *sme = addApp(s, list, configDialog_->category->currentText()); sme->rank = 0xFFFFFF; // hype rank to max, i.e. keep this entry on top of everything - for this session or until first use sme->show(); sort(); } void AppList::removeEntry() { popupBlocked_ = true; if (KMessageBox::questionYesNo (this, i18n("Are you sure you want to remove
%1
").arg(handledEntry->title()), i18n("Remove ALI entry")) == KMessageBox::Yes) { tqWarning("gonna delete!"); writeEntry(handledEntry->m_service->locateLocal(), true); handledEntry->hide(); entryList.removeRef(handledEntry); delete handledEntry; handledEntry = 0L; } popupBlocked_ = false; } void AppList::editDialog() { if (!handledEntry) return; popupBlocked_ = true; disconnect (((TQObject*)configDialog_->buttonOk), SIGNAL(clicked()), this, 0); connect (((TQObject*)configDialog_->buttonOk), SIGNAL(clicked()), this, SLOT(editEntry())); configDialog_->appName->setText(handledEntry->m_service->name()); configDialog_->category->setCurrentItem (handledEntry->groupPath, false); configDialog_->showInSystray->setChecked( handledEntry->m_service->exec().contains("ksystraycmd ") ); if (!configDialog_->showInSystray->isChecked()) configDialog_->command->setURL(handledEntry->m_service->exec()); else configDialog_->command->setURL(handledEntry->m_service->exec().right(handledEntry->m_service->exec().length() - (handledEntry->m_service->exec().findRev("ksystraycmd ") + 12))); configDialog_->genericName->setText(handledEntry->m_service->genericName()); configDialog_->iconButton->setIcon(handledEntry->m_service->icon ()); configDialog_->keywords->setText(handledEntry->m_service->keywords().join(",")); configDialog_->startupFeedback->setChecked( handledEntry->m_service->property ( "StartupNotify" ).toBool()); configDialog_->description->setText(handledEntry->m_service->comment()); configDialog_->startInTerminal->setChecked( handledEntry->m_service->terminal() ); configDialog_->terminalSettings->setText(handledEntry->m_service->terminalOptions()); configDialog_->startAsUser->setChecked( handledEntry->m_service->substituteUid() ); configDialog_->username->setText(handledEntry->m_service->username()); configDialog_->workingDir->setURL(handledEntry->m_service->path()); // KKeyButton* shortcut; configDialog_->setCaption ( i18n("Edit Entry") ); ((TQWidget*)(configDialog_->extendedGroup))->hide(); configDialog_->buttonDetail->setDown ( false ); configDialog_->adjustSize(); configDialog_->show(); } void AppList::editEntry() { TQString fullpath; if (handledEntry->groupPath == configDialog_->category->currentText()) // group not changed fullpath = handledEntry->m_service->locateLocal(); // find a local replacement path else // more complex: remove (del/shadow) entry from old group and create one in the new group { writeEntry(handledEntry->m_service->locateLocal(), true); //hide from old group fullpath = configDialog_->category->currentText(); while (fullpath[0] == '/') // remove leading "/"'s fullpath.remove(0,1); fullpath = KService::newServicePath(true, fullpath + configDialog_->appName->text()); // find new path } writeEntry(fullpath); handledEntry->hide(); TQDate lu = handledEntry->lastUse; uint u = handledEntry->usage; entryList.removeRef(handledEntry); delete handledEntry; handledEntry = 0L; KService *s = new KService(fullpath); TQStringList list(KServiceGroup::group(configDialog_->category->currentText())->caption()); StartMenuEntry *sme = addApp(s, list, configDialog_->category->currentText()); sme->lastUse = lu; sme->usage = u; sme->rank = 8 + u - lu.daysTo(TQDate::currentDate()); if (!config) config = new KConfig("bStarter", false, false); config->setGroup("Statistics"); sme->saveStats(); delete config; config = 0L; sme->show(); sort(); popupBlocked_ = false; } void AppList::writeEntry(TQString path, bool hidden ) { KConfig *config = new KConfig(path); config->setDesktopGroup(); if (!configDialog_->description->text().isEmpty()) config->writeEntry("Comment", configDialog_->description->text()); if (!configDialog_->command->url().isEmpty()) if (configDialog_->showInSystray->isChecked()) config->writeEntry("Exec", "ksystraycmd " + configDialog_->command->url()); else config->writeEntry("Exec", configDialog_->command->url()); if (!configDialog_->genericName->text().isEmpty()) config->writeEntry("GenericName", configDialog_->genericName->text()); if (hidden) config->writeEntry("Hidden", true); else if (config->readBoolEntry("Hidden", false)) config->writeEntry("Hidden", false); if (!configDialog_->iconButton->icon().isNull()) config->writeEntry("Icon", configDialog_->iconButton->icon()); if (!configDialog_->keywords->text().isEmpty()) config->writeEntry("Keywords", TQStringList::split(',', configDialog_->keywords->text())); if (!configDialog_->appName->text().isEmpty()) config->writeEntry("Name", configDialog_->appName->text()); if (!configDialog_->workingDir->url().isEmpty()) config->writeEntry("Path", configDialog_->workingDir->url()); if (configDialog_->startupFeedback->isChecked()) config->writeEntry("StartupNotify", true); if (configDialog_->startInTerminal->isChecked()) { config->writeEntry("Terminal", 1); if (!configDialog_->terminalSettings->text().isEmpty()) config->writeEntry("TerminalOptions", configDialog_->terminalSettings->text()); } config->writeEntry("Type", "Application"); if (configDialog_->startAsUser->isChecked()) { config->writeEntry("X-KDE-SubstituteUID", true); if (!configDialog_->username->text().isEmpty()) config->writeEntry("X-KDE-Username", configDialog_->username->text()); } delete config; // configDialog_->category->setCurrentItem (handledEntry->m_service->categories().join("/"), true); } void AppList::popup(StartMenuEntry* entry) { if (popupBlocked_ && configDialog_->isShown()) return; handledEntry = entry; m_popup->popup(TQCursor::pos()); } void AppList::sort() { // first clean the layout (i assume that TQLayout::remove() will search from beginning so removing over the current order will be quite fast) TQPtrListIterator it(entryList); StartMenuEntry *runner; while( (runner = it.current()) != 0 ) { ++it; m_VLayout->remove ( runner ); } ((MyVBoxLayout*)m_VLayout)->deleteAllItems(); // get rid of the stretch // then sort the list entryList.sort(); it.toFirst(); // now rebuild the layout from new list while( (runner = it.current()) != 0 ) { ++it; m_VLayout->addWidget ( runner ); } m_VLayout->addStretch(1); // add final stretch } void AppList::init() { m_root = KServiceGroup::group(TQString::null); if (!m_root || !m_root->isValid()) { tqWarning("ROOT NOT FOUND"); return; } favItemAmount = config->readNumEntry("FavItemAmount", 10); neewbieApps << "konqueror" << "kmail" << "kppp"; if (newbie = config->readBoolEntry("firstUse", true)) // '/' is certainly not unescaped part of a filename ;) { infoLabel->setText ( i18n("First Session Applications") ); // delete config; // config = 0L; } else { infoLabel->setText ( i18n("Favorite Applications
") ); } config->setGroup("Statistics"); TQStringList captions, paths; insertGroup(m_root, captions, paths); paths.sort(); configDialog_->category->insertStringList(paths); configDialog_->category->completionObject()->setCompletionMode( KGlobalSettings::CompletionPopupAuto ); configDialog_->category->completionObject()->insertItems(paths); // if (config) { delete config; config = 0L; } sort(); reset(); } void AppList::save(KConfig *config) { config->setGroup("Statistics"); TQPtrListIterator it(entryList); StartMenuEntry *runner; while( (runner = it.current()) != 0 ) { ++it; runner->saveStats(); } } void AppList::insertGroup(KServiceGroup *g, TQStringList & captions, TQStringList & paths) { KServiceGroup::List list = g->entries(true, true, false, false); if (list.isEmpty()) { return; } else { captions.append(g->caption()); if (!categories.contains(g->caption())) categories.append(g->caption()); if (!paths.contains(g->relPath())) paths.append(g->relPath()); for( KServiceGroup::List::ConstIterator it = list.begin(); it != list.end(); it++) { KSycocaEntry *p = (*it); if (p->isType(KST_KService)) { KService *s = static_cast(p); if ((s->name().at(0) == '.')) continue; if (s->type() == "Application") { addApp(s, captions, g->relPath()); } } else if (p->isType(KST_KServiceGroup)) { KServiceGroup *g2 = static_cast(p); if ((g2->name().at(0) == '.')) continue; insertGroup(g2,captions, paths); } } captions.remove(g->caption()); } } StartMenuEntry* AppList::addApp(KService * s, TQStringList & captions, TQString relPath) { StartMenuEntry * tmp = new StartMenuEntry(s, relPath, _size, neewbieApps.find(s->desktopEntryName()) != neewbieApps.end(), m_widget); connect (tmp, SIGNAL(appUp()), this, SLOT(appUp())); connect (tmp, SIGNAL(appDown()), this, SLOT(appDown())); connect (tmp, SIGNAL(appLeft()), this, SLOT(appLeft())); connect (tmp, SIGNAL(hovered(const TQString&)), this, SIGNAL(message(const TQString&))); if (useKTTS) connect (tmp, SIGNAL(sayText(const TQString&)), this, SIGNAL(sayText(const TQString&))); connect (tmp, SIGNAL(unhovered()), this, SIGNAL(clearStatus())); connect (tmp, SIGNAL(pressed()), parent(), SLOT(close())); connect (tmp, SIGNAL(popup(StartMenuEntry*)), this, SLOT(popup(StartMenuEntry*))); connect (tmp, SIGNAL(closeMenu()), parent(), SLOT(close())); connect (tmp, SIGNAL(executed()), this, SLOT(sort())); m_VLayout->addWidget(tmp); tmp->hide(); entryList.append(tmp); KeyWordList::Iterator it; if (!(s->name().isNull() || s->name().isEmpty())) { it = m_keywordList.insert(s->name(), StartMenuEntryList(), false); it.data().append( tmp ); } TQStringList kw; #if 0 kw = s->categories(); // THIS IS ****IMPORTANT***** kicker will crash on init if you try to grep through the pointers! if (!kw.isEmpty()) { TQStringList::Iterator key; for ( key = kw.begin(); key != kw.end(); ++key ) { if (!((*key).isNull() || (*key).isEmpty())) { it = m_keywordList.insJediKnightert(*key, StartMenuEntryList(), false); it.data().append( tmp ); } } } #endif kw = s->keywords(); // THIS IS ****IMPORTANT***** kicker will crash on init if you try to grep through the pointers! if (!kw.isEmpty()) { for ( TQStringList::Iterator key = kw.begin(); key != kw.end(); ++key ) { if (!((*key).isNull() || (*key).isEmpty())) { it = m_keywordList.insert(*key, StartMenuEntryList(), false); it.data().append( tmp ); } } } // group captions (so Games/IDSoftware/Quake3 will appear in Games and IDSoftware) if (!captions.isEmpty()) { for ( TQStringList::Iterator key = captions.begin(); key != captions.end(); ++key ) { if (!((*key).isNull() || (*key).isEmpty())) { it = m_groupList.insert(*key, StartMenuEntryList(), false); it.data().append( tmp ); } } } return tmp; } void AppList::finish() { entryList.last(); entryList.next(); m_VLayout->addStretch(1); categories.sort(); } void AppList::appDown() { StartMenuEntry *save; if (entryList.current() == 0L/*entryList.getLast()*/) { entryList.first(); save = 0L; } else { save = entryList.current(); entryList.next(); } for ( StartMenuEntry *runner = entryList.current(); runner; runner = entryList.next() ) if (runner->isShown()) { if (save) save->clearFocus(); runner->setFocus(); TQPoint pt(0,runner->height()); pt = runner->mapToParent(pt); ensureVisible ( pt.x(), pt.y()); return; } // if (currentEntry == entryList.end()) // currentEntry = entryList.begin(); // keep this somewhere valid } void AppList::appUp() { if (entryList.current() == entryList.getFirst()) { entryList.current()->clearFocus(); entryList.last(); entryList.next(); // we jump out emit looseKey(); return; } StartMenuEntry *save = entryList.current(); StartMenuEntry *runner; if (entryList.current()) runner = entryList.prev(); else runner = entryList.last(); for ( ; runner != entryList.getFirst(); runner = entryList.prev()) if (runner->isShown()) { if (save) save->clearFocus(); runner->setFocus(); TQPoint pt(0,0); pt = runner->mapToParent(pt); ensureVisible ( pt.x(), pt.y()); return; } if (runner == entryList.getFirst()) { if (save) save->clearFocus(); if (runner->isShown()) { runner->setFocus(); TQPoint pt(0,0); pt = runner->mapToParent(pt); ensureVisible ( pt.x(), pt.y()); } else { entryList.last(); entryList.next();// we jump out emit looseKey(); } } } void AppList::appLeft() { if (entryList.current()) { entryList.current()->clearFocus(); entryList.last(); entryList.next(); // we jump out } emit looseKey(); } void AppList::showCategory(const TQString & string) { infoLabel->setText(string); infoLabel->show(); StartMenuEntry *it2; KeyWordList::Iterator it; for ( it = m_groupList.begin(); it != m_groupList.end(); ++it ) { if (it.key() == string) { for ( it2 = it.data().first(); it2; it2 = it.data().next()) it2->display = true; } else { for ( it2 = it.data().first(); it2; it2 = it.data().next()) it2->display = it2->display || false; } } uint visibleItems = 0; for ( it2 = entryList.first(); it2; it2 = entryList.next()) { if (it2->display) { visibleItems++; it2->show(); } else it2->hide(); it2->display = false; } if (useKTTS && visibleItems == 0) { TQString text = i18n("for TTS output, informs the user that no entries are in the currently selected group", "Warning! No Applications in group %1").arg(string); emit sayText(text); } } void AppList::search(const TQString & string) { StartMenuEntry *it2; if (string == TQString::null || string == "") // empty line - remove all and exit { infoLabel->setText ( i18n("Favorite Applications
") ); infoLabel->show(); int i = 0; for ( it2 = entryList.first(); it2; it2 = entryList.next() ) { i < favItemAmount ? it2->show() : it2->hide(); i++; } return; } infoLabel->hide(); // ok, we need a 2pass search: 1st to figure out which to show, 2nd to show or hide things // the implementation also prevents us from spending time on showing/hiding things and some onscreen flicker, O(k*n(k)*n) KeyWordList::Iterator it; //keywords for ( it = m_keywordList.begin(); it != m_keywordList.end(); ++it ) { if (it.key().contains(string, false) > 0) { for ( it2 = it.data().first(); it2; it2 = it.data().next()) it2->display = true; } else { for ( it2 = it.data().first(); it2; it2 = it.data().next()) it2->display = it2->display || false; } } //groups for ( it = m_groupList.begin(); it != m_groupList.end(); ++it ) { if (it.key().contains(string, false) > 0) { for ( it2 = it.data().first(); it2; it2 = it.data().next()) it2->display = true; } else { for ( it2 = it.data().first(); it2; it2 = it.data().next()) it2->display = it2->display || false; } } //items uint visibleItems = 0; for ( it2 = entryList.first(); it2; it2 = entryList.next()) { if (it2->display && visibleItems < 50) //limit this to a healthy size { visibleItems++; it2->show(); } else it2->hide(); it2->display = false; } if (useKTTS && visibleItems == 0) { TQString text = i18n("for TTS output, no entries match the current search text", "Warning! No more Applications left. The entered Text is %1").arg(spell(string)); emit sayText(text); } } void AppList::clear() { for ( StartMenuEntry *it = entryList.first(); it; it = entryList.next()) it->hide(); } void AppList::reset() { newbie ? infoLabel->setText ( i18n("First Session Applications") ) : infoLabel->setText ( i18n("Favorite Applications
") ); infoLabel->show(); if (newbie) { for ( StartMenuEntry *it = entryList.first(); it; it = entryList.next()) { it->forNewbie ? it->show() : it->hide(); } } else { uint i = 0; for ( StartMenuEntry *it = entryList.first(); it; it = entryList.next()) { i < favItemAmount ? it->show() : it->hide(); i++; } } setContentsPos(0, 0); } StartMenu::StartMenu( int size, TQWidget * parent, WFlags f ) : TQWidget(parent, "StartMenu", f), _size(size), inMove(false) { m_panelPos = StartMenu::Nowhere; panelLayout = new TQGridLayout ( this, 3, 3 ); config = new KConfig("bStarter", true, false); config->setGroup("Shell"); history = config->readListEntry("History"); config->setGroup("Settings"); if (useKTTS = config->readBoolEntry("useKTTS", false)) m_spokenText = 0; _filterData = new KURIFilterData(); int r,g,b,r2,g2,b2; KGlobalSettings::baseColor().getRgb(&r,&g,&b); KGlobalSettings::textColor().getRgb(&r2,&g2,&b2); commentColor.setRgb((r+r2)/2,(g+g2)/2,(b+b2)/2); infoColor.setRgb((3*r+r2)/4,(3*g+g2)/4,(3*b+b2)/4); currentHistoryItem = history.end(); header = new TQWidget(this, "_B_ALI_HEADER"); header->installEventFilter(this); TQHBoxLayout *headerLayout = new TQHBoxLayout(header, 5, 3); userButton = new StartMenuButton(_size, "folder_home", TQString(getenv("USER")), "~", StartMenuButton::Status, header, "_B_ALI_HEADER"); headerLayout->addWidget(userButton); header->setPaletteBackgroundColor(KGlobalSettings::highlightColor()); connect (userButton, SIGNAL(pressed(const TQString &)), this, SLOT(execute(const TQString &))); connect (userButton, SIGNAL(pressed(const TQString &)), this, SLOT(close())); TQBoxLayout *mainLayout = new TQVBoxLayout(); panelLayout->addLayout(mainLayout, 1, 1); mainLayout->addWidget(header); mainLayout->addSpacing ( 3 ); TQBoxLayout *centerLayout = new TQHBoxLayout( mainLayout ); centerLayout->addSpacing ( 3 ); appList = new AppList(_size, this); appList->setSizePolicy(TQSizePolicy::Expanding,TQSizePolicy::Expanding); appList->finish(); searchLine = new SearchLine(header); categoryCombo = new TQComboBox(header, "_B_ALI_HEADER"); headerLayout->addWidget(categoryCombo); categoryCombo->setLineEdit ( searchLine ); categoryCombo->insertStringList(appList->categories); categoryCombo->setEditable ( true ); categoryCombo->setInsertionPolicy(TQComboBox::NoInsertion); searchLine->installEventFilter(this); searchLine->setCompletionMode(KGlobalSettings::CompletionAuto); config->setGroup("Shortcuts"); // read shortcuts... TQStringList cuts = config->readListEntry ("Shortcuts", ','); TQStringList cats = config->readListEntry ("Categories", ','); TQStringList::Iterator it; TQStringList::Iterator it2 = cats.begin(); for ( it = cuts.begin(); it != cuts.end(); ++it ) { if (it2 == cats.end()) break; shortcutList.insert(MyKey((*it)),(*it2)); it2++; } //--- TQString PATH(getenv("PATH")); int n = PATH.contains(':', false); TQStringList list; for (int i = 0; i < n; i++) { TQDir execDir(PATH.section(':', i, i)); list = execDir.entryList(TQDir::Files | TQDir::Executable, TQDir::Name | TQDir::IgnoreCase ); searchLine->completionObject()->insertItems(list); } connect (categoryCombo, SIGNAL(activated( const TQString &)), appList, SLOT(showCategory(const TQString &))); connect (searchLine, SIGNAL(typedTextChanged(const TQString &)), appList, SLOT(search(const TQString &))); connect (searchLine, SIGNAL(textChanged(const TQString &)), this, SLOT(endHistory())); connect (appList, SIGNAL(looseKey()), searchLine, SLOT(setFocus())); connect (appList, SIGNAL(looseKey()), searchLine, SLOT(selectAll() )); connect (kapp, SIGNAL(shutDown()), this, SLOT(save() )); if (useKTTS) connect (appList, SIGNAL(sayText(const TQString&)), this, SLOT(sayText(const TQString&) )); centerLayout->addWidget(appList,10); centerLayout->addSpacing ( 3 ); m_panel = new Panel(_size, this, "_B_ALI_HEADER"); // m_panel->installEventFilter(this); m_panel->setFixedHeight(_BIGSIZE_(_size)+4); statusBar = new KSqueezedTextLabel(this); TQFont tmpFnt = statusBar->font(); tmpFnt.setBold(true); statusBar->setFont(tmpFnt); connect (appList, SIGNAL(message(const TQString&)), this, SLOT(message(const TQString&) )); connect (appList, SIGNAL(clearStatus()), this, SLOT(clearStatus() )); connect (m_panel, SIGNAL(message(const TQString&)), this, SLOT(centerMessage(const TQString&) )); connect (m_panel, SIGNAL(clearStatus()), this, SLOT(clearStatus() )); mainLayout->addSpacing ( 3 ); mainLayout->addWidget ( statusBar ); panelLayout->addWidget ( m_panel, 2, 1 ); m_panel->hide(); if (config) { delete config; config = 0L; } // KDrawer *drawer = new KDrawer(this, KDrawer::Bottom); } void StartMenu::save() { config = new KConfig("bStarter", false, false); config->setGroup("Shell"); TQStringList lst; for ( TQStringList::Iterator it = history.begin(); it != history.end(); ++it ) lst.prepend(*it); config->writeEntry("History", lst); config->setGroup("Settings"); config->writeEntry("firstUse", false); appList->save(config); m_panel->save(config); delete config; config = 0L; } #if 0 extern int kicker_screen_number; void StartMenu::slotLock() { TQCString appname( "kdesktop" ); // if ( kicker_screen_number ) // appname.sprintf("kdesktop-screen-%d", kicker_screen_number); kapp->dcopClient()->send(appname, "KScreensaverIface", "lock()", ""); } #endif void StartMenu::reloadIcons( int size) { _size = size; m_panel->reloadIcons(size); appList->reloadIcons(size); } void StartMenu::setCategory(const TQString & category) { categoryCombo->setCurrentItem ( categoryCombo->listBox()->index(categoryCombo->listBox()->findItem(category, TQt::ExactMatch))); //emit categoryCombo->activated ( category ); // dunno if i'll need that once, needs protected access appList->showCategory(category); } void StartMenu::updateShortcuts(ShortcutList & list) { shortcutList = list; } void StartMenu::toggleKTTS(bool on) { useKTTS = on; if (useKTTS) { m_spokenText = 0; TQPtrListIterator it(appList->entryList); StartMenuEntry *runner; while( (runner = it.current()) != 0 ) { ++it; connect (runner, SIGNAL(sayText(const TQString&)), this, SIGNAL(sayText(const TQString&))); } connect (appList, SIGNAL(sayText(const TQString&)), this, SLOT(sayText(const TQString&) )); } else { TQPtrListIterator it(appList->entryList); StartMenuEntry *runner; while( (runner = it.current()) != 0 ) { ++it; disconnect (runner, SIGNAL(sayText(const TQString&)), this, SIGNAL(sayText(const TQString&))); } disconnect (appList, SIGNAL(sayText(const TQString&)), this, SLOT(sayText(const TQString&) )); } } SearchLine::SearchLine( TQWidget * parent ) : KLineEdit(parent){blocked = false;}; void SearchLine::makeCompletion (const TQString & string) { if (blocked) {blocked = false; return;} emit typedTextChanged(string); KLineEdit::makeCompletion (string); } StartMenu::~StartMenu() { // appList->save(); } void StartMenu::sayText(const TQString &text) { // strip tags TQString cleanText; bool copy = true; for (uint i = 0; i < text.length(); i++) { if (!copy && text[i] == '>') // end tag, set copy true and move on { copy = true; continue; } if (copy && text[i] == '<') // tag start, set copy false and move on { copy = false; continue; } if (copy) //copy char ;) cleanText += text[i]; } // done TQByteArray data1; TQDataStream arg1(data1, IO_WriteOnly); arg1 << m_spokenText; // stop what we messaged before (if) if (!kapp->dcopClient()->send("kttsd", "kspeech", "stopText(uint)", data1)) tqDebug("there was some error using DCOP."); TQByteArray data, replyData; TQCString replyType; TQDataStream arg(data, IO_WriteOnly); arg << cleanText << ""; // ask for the full list if (!kapp->dcopClient()->call("kttsd", "kspeech", "sayText(TQString, TQString)", data, replyType, replyData)) tqDebug("there was some error using DCOP."); else { TQDataStream reply(replyData, IO_ReadOnly); if (replyType == "uint") reply >> m_spokenText; else tqWarning("properties() returned an unexpected type of reply (%s)!",TQString(replyType).ascii()); } } void StartMenu::show() { m_panel->setBackgroundOrigin(TQWidget::WidgetOrigin); statusBar->setBackgroundOrigin(TQWidget::ParentOrigin); searchLine->setText(i18n("Type to search or enter a command")); searchLine->selectAll(); searchLine->setFocus(); // KWin::setOpacity(winId(), 80); TQWidget::show(); } void StartMenu::hide() { emit aboutToHide(); searchLine->clear(); appList->reset(); TQWidget::hide(); } void StartMenu::message(const TQString &text) { statusBar->setAlignment ( TQt::AlignAuto | TQt::AlignVCenter ); statusBar->setText(text); } void StartMenu::centerMessage(const TQString &text) { statusBar->setAlignment ( TQt::AlignCenter ); statusBar->setText(text); } void StartMenu::clearStatus() { statusBar->clear(); } void StartMenu::setPanelPosition(PanelPosition p) { if (p == m_panelPos) return; panelLayout->remove(m_panel); switch (p) { case StartMenu::South: m_panel->show(); if (m_panelPos == StartMenu::Nowhere || m_panelPos == StartMenu::West || m_panelPos == StartMenu::East ) { // m_panel->set2SizePolicies(TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed); m_panel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed); m_panel->setOrientation ( TQt::Horizontal ); m_panel->setFixedHeight(_BIGSIZE_(_size)+4); m_panel->setMaximumWidth(32767); } panelLayout->addWidget(m_panel, 2, 1); break; case StartMenu::West: m_panel->show(); if (m_panelPos == StartMenu::Nowhere || m_panelPos == StartMenu::South || m_panelPos == StartMenu::North ) { // m_panel->set2SizePolicies(TQSizePolicy::Fixed, TQSizePolicy::MinimumExpanding); m_panel->setSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Expanding); m_panel->setOrientation ( TQt::Vertical ); m_panel->setFixedWidth(_BIGSIZE_(_size)+4); m_panel->setMaximumHeight(32767); } panelLayout->addWidget(m_panel, 1, 0); break; case StartMenu::East: m_panel->show(); if (m_panelPos == StartMenu::Nowhere || m_panelPos == StartMenu::South || m_panelPos == StartMenu::North ) { // m_panel->set2SizePolicies(TQSizePolicy::Fixed, TQSizePolicy::MinimumExpanding); m_panel->setSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Expanding); m_panel->setOrientation ( TQt::Vertical ); m_panel->setFixedWidth(_BIGSIZE_(_size)+4); m_panel->setMaximumHeight(32767); } panelLayout->addWidget(m_panel, 1, 2); break; case StartMenu::North: m_panel->show(); if (m_panelPos == StartMenu::Nowhere || m_panelPos == StartMenu::West || m_panelPos == StartMenu::East ) { // m_panel->set2SizePolicies(TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed); m_panel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed); m_panel->setOrientation ( TQt::Horizontal ); m_panel->setFixedHeight(_BIGSIZE_(_size)+4); m_panel->setMaximumWidth(32767); } panelLayout->addWidget(m_panel, 0, 1); break; default: m_panel->hide(); // break; } m_panelPos = p; } void StartMenu::execute(const TQString& command) // adapted from kicker run applet - far more convenient ;) { history.remove(command); history.append(command); // all - the list is not stored and the user may want to easily correct mistypes of LOOOOOOOOOOOOOOOOOOOONG commands with a lot of "\ "... ;P TQString exec; kapp->propagateSessionManager(); _filterData->setData( command.stripWhiteSpace() ); TQStringList filters; filters << "kurisearchfilter" << "kshorturifilter"; KURIFilter::self()->filterURI( *(_filterData), filters ); TQString cmd = (_filterData->uri().isLocalFile() ? _filterData->uri().path():_filterData->uri().url()); // Nothing interesting. Quit! if ( cmd.isEmpty() ) { return; } else if (cmd == "logout") { close(); kapp->requestShutDown(); } else { switch( _filterData->uriType() ) { case KURIFilterData::LOCAL_FILE: case KURIFilterData::LOCAL_DIR: case KURIFilterData::NET_PROTOCOL: case KURIFilterData::HELP: { (void) new KRun( _filterData->uri() ); return; } case KURIFilterData::EXECUTABLE: case KURIFilterData::SHELL: { exec = cmd; if( _filterData->hasArgsAndOptions() ) cmd += _filterData->argsAndOptions(); break; } case KURIFilterData::UNKNOWN: case KURIFilterData::ERROR: default: return; } } KRun::runCommand( cmd, exec, "" ); return; } void StartMenu::endHistory() { currentHistoryItem = history.end(); } void StartMenu::search(const TQString & string) { disconnect (searchLine, SIGNAL(textChanged ( const TQString & )), this, SLOT(search(const TQString &))); appList->search(string); } bool StartMenu::eventFilter ( TQObject * o, TQEvent * e ) { if (o == header) { if (e->type() == TQEvent::MouseButtonPress && ((TQMouseEvent*)e)->button() == TQt::LeftButton) { inMove = true; movePoint = ((TQMouseEvent*)e)->pos(); header->grabMouse(TQt::SizeAllCursor); return true; } else if (e->type() == TQEvent::MouseButtonRelease && ((TQMouseEvent*)e)->button() == TQt::LeftButton) { inMove = false; header->releaseMouse(); return true; } else if (e->type() == TQEvent::MouseMove && inMove) { move(((TQMouseEvent*)e)->globalPos() - movePoint); return true; } else if (e->type() == TQEvent::Resize && ((TQResizeEvent*)e)->size().height() != ((TQResizeEvent*)e)->oldSize().height()) { int height = ((TQResizeEvent*)e)->size().height(); KPixmap bgPix = TQPixmap(32, height); KPixmap bgPix1 = TQPixmap(32, height/2); KPixmap bgPix2 = TQPixmap(32, height - bgPix1.height()); TQColor buttonColor = ((TQWidget*)o)->palette().color(TQPalette::Active, TQColorGroup::Button); KPixmapEffect::gradient( bgPix1, buttonColor.light(130), buttonColor, KPixmapEffect::VerticalGradient, 0); KPixmapEffect::gradient( bgPix2, buttonColor.dark(120), buttonColor.light(110), KPixmapEffect::VerticalGradient, 0); TQPainter p(&bgPix); p.drawPixmap(0,0,bgPix1); p.drawPixmap(0,bgPix1.height(),bgPix2); p.end(); ((TQWidget*)o)->setPaletteBackgroundPixmap( bgPix ); } return false; } if (o != searchLine) return false; TQLineEdit *le = (TQLineEdit *)o; if (e->type() == TQEvent::KeyPress) { TQKeyEvent *ke = (TQKeyEvent*)e; if (ke->state() & TQt::ControlButton || ke->state() & TQt::AltButton) // might be shortcut, set category { if (ke->state() == TQt::ControlButton) { if (ke->key() == TQt::Key_Up) { if (categoryCombo->currentItem() > 0) { categoryCombo->setCurrentItem ( categoryCombo->currentItem() - 1 ); appList->showCategory(categoryCombo->currentText()); } return true; } if (ke->key() == TQt::Key_Down) { if (categoryCombo->currentItem() < categoryCombo->count()) { categoryCombo->setCurrentItem ( categoryCombo->currentItem() + 1 ); appList->showCategory(categoryCombo->currentText()); } return true; } } if (ke->key() == TQt::Key_Shift || ke->key() == TQt::Key_Control || ke->key() == TQt::Key_Alt) return false; ShortcutList::Iterator it; for ( it = shortcutList.begin(); it != shortcutList.end(); ++it ) { if (it.key().modFlags() == ke->state() && it.key().key() == ke->key()) setCategory( it.data() ); } return true; //fire event to prevent lienedit action like ctrl+d -> del etc. } switch(ke->key()) { case TQt::Key_Return: case TQt::Key_Enter: { execute(le->text()); if (!(ke->state() & TQt::ControlButton)) close(); //bye return true; //don't do anything else } case TQt::Key_Backspace: case TQt::Key_Delete: { connect (le, SIGNAL(textChanged ( const TQString & )), this, SLOT(search(const TQString &))); break; } case TQt::Key_Down: { if (history.isEmpty() || currentHistoryItem == history.end()) { appList->appDown(); } else // navigate history { le->blockSignals(true); le->setText(*currentHistoryItem); le->blockSignals(false); currentHistoryItem++; if (currentHistoryItem == history.end()) le->selectAll(); } return true; //don't scroll the categories } case TQt::Key_Up: { if (!(history.isEmpty() || currentHistoryItem == history.begin())) { currentHistoryItem--; le->blockSignals(true); le->setText(*currentHistoryItem); le->blockSignals(false); } return true; //don't scroll the categories } case TQt::Key_Escape: { close(); //bye break; } default: break; } return false; } else if (isVisible() && useKTTS && e->type() == TQEvent::FocusIn) { TQString text = i18n("TTS output", "The searchline has now the focus."); sayText(text); } return false; }