//============================================================================= // // File : kvi_customtoolbar.cpp // Created on Sun 21 Nov 2004 05:28:57 by Szymon Stefanek // // This file is part of the KVIrc IRC Client distribution // Copyright (C) 2004 Szymon Stefanek // // 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 opinion) any later version. // // This program is distributed in the HOPE that it will be USEFUL, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, // Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= #define __KVIRC__ #include "kvi_customtoolbar.h" #include "kvi_frame.h" #include "kvi_locale.h" #include "kvi_app.h" #include "kvi_actionmanager.h" #include "kvi_customtoolbardescriptor.h" #include #include "kvi_tal_popupmenu.h" #include #include #include #include #include #include #ifdef COMPILE_USE_QT4 #include #include #define TQDragObject Q3DragObject #define TQTextDrag Q3TextDrag #define TQIconDrag Q3IconDrag #include #else #include #include #endif KviCustomToolBarSeparator::KviCustomToolBarSeparator(KviCustomToolBar *pParent,const char * name) : TQWidget(pParent,name) { m_pToolBar = pParent; setBackgroundMode(pParent->backgroundMode()); setBackgroundOrigin(ParentOrigin); setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum,TQSizePolicy::Minimum)); } TQSize KviCustomToolBarSeparator::sizeHint() const { #ifdef COMPILE_USE_QT4 TQStyleOption opt; opt.initFrom(this); int extent = style()->pixelMetric(TQStyle::PM_ToolBarSeparatorExtent,&opt,this); #else int extent = style().pixelMetric(TQStyle::PM_DockWindowSeparatorExtent,this); #endif if(m_pToolBar->orientation() == Qt::Horizontal)return TQSize(extent,0); else return TQSize(0,extent); } void KviCustomToolBarSeparator::paintEvent(TQPaintEvent *) { TQPainter p(this); #ifdef COMPILE_USE_QT4 TQStyleOption opt; opt.initFrom(this); style()->drawPrimitive(TQStyle::PE_Q3DockWindowSeparator,&opt,&p,this); #else TQStyle::SFlags flags = TQStyle::Style_Default; if(m_pToolBar->orientation() == Qt::Horizontal)flags |= TQStyle::Style_Horizontal; style().tqdrawPrimitive(TQStyle::PE_DockWindowSeparator,&p,rect(),colorGroup(),flags); #endif } KviCustomToolBar::KviCustomToolBar(KviCustomToolBarDescriptor * d,const TQString &label,TQT_TOOLBARDOCK_TYPE dock,bool bNewLine,const char * nam) : KviToolBar(label,dock,bNewLine,nam) { m_pDescriptor = d; m_pMovedChild = 0; m_pDraggedChild = 0; m_pFilteredChildren = 0; setAcceptDrops(true); connect(KviActionManager::instance(),TQT_SIGNAL(beginCustomizeToolBars()),this,TQT_SLOT(beginCustomize())); connect(KviActionManager::instance(),TQT_SIGNAL(endCustomizeToolBars()),this,TQT_SLOT(endCustomize())); setMinimumSize(20,20); d->registerToolBar(this); if(KviActionManager::customizingToolBars()) beginCustomize(); // because we will not get the signal } KviCustomToolBar::~KviCustomToolBar() { if(KviActionManager::customizingToolBars()) syncDescriptor(); // because we will not get endCustomize() m_pDescriptor->unregisterToolBar(this); if(KviActionManager::customizingToolBars()) { if(KviActionManager::currentToolBar() == this) KviActionManager::instance()->setCurrentToolBar(0); } if(m_pFilteredChildren)delete m_pFilteredChildren; } void KviCustomToolBar::paintEvent(TQPaintEvent * e) { KviToolBar::paintEvent(e); if(KviActionManager::customizingToolBars() && (KviActionManager::currentToolBar() == this)) { TQPainter p(this); p.setPen(TQt::red); p.drawRect(0,0,width(),height()); } } void KviCustomToolBar::filteredChildDestroyed() { if(!m_pFilteredChildren)return; const TQObject * o = TQT_TQOBJECT(const_cast(sender())); m_pFilteredChildren->remove((void *)o); } void KviCustomToolBar::filterChild(TQObject * o) { bool * b = new bool(((TQWidget *)o)->isEnabled()); if(m_pFilteredChildren) m_pFilteredChildren->insert(o,b); if(!*b)((TQWidget *)o)->setEnabled(true); o->installEventFilter(this); connect(o,TQT_SIGNAL(destroyed()),this,TQT_SLOT(filteredChildDestroyed())); } void KviCustomToolBar::unfilterChild(TQObject * o) { if(m_pFilteredChildren) { bool * b = m_pFilteredChildren->find(o); if(b) { if(!*b)((TQWidget *)o)->setEnabled(false); o->removeEventFilter(this); disconnect(o,TQT_SIGNAL(destroyed()),this,TQT_SLOT(filteredChildDestroyed())); } } } void KviCustomToolBar::beginCustomize() { if(m_pFilteredChildren)delete m_pFilteredChildren; m_pFilteredChildren = new KviPointerHashTable; m_pFilteredChildren->setAutoDelete(true); // filter the events for all the children #ifdef COMPILE_USE_QT4 TQPtrList l = children(); for(TQPtrList::Iterator it = l.begin();it != l.end();++it) { if((*it)->isWidgetType()) filterChild(*it); } #else const TQObjectList l = childrenListObject(); TQObjectListIterator it(l); while(TQObject * o = it.current()) { if(o->isWidgetType()) filterChild(o); ++it; } #endif } void KviCustomToolBar::endCustomize() { // stop filtering events #ifdef COMPILE_USE_QT4 TQPtrList l = children(); for(TQPtrList::Iterator it = l.begin();it != l.end();++it) { if((*it)->isWidgetType()) unfilterChild(*it); } #else const TQObjectList l = childrenListObject(); TQObjectListIterator it(l); while(TQObject * o = it.current()) { if(o->isWidgetType()) unfilterChild(o); ++it; } #endif // FIXME: We SHOULD MAKE SURE that the children are re-enabled... // this could be done by calling setEnabled(isEnabled()) on each action ? if(m_pFilteredChildren) { delete m_pFilteredChildren; m_pFilteredChildren = 0; } syncDescriptor(); } void KviCustomToolBar::syncDescriptor() { // store the item order in the descriptor TQBoxLayout * lay = boxLayout(); TQLayoutIterator iter = lay->iterator(); TQLayoutItem * i; m_pDescriptor->actions()->clear(); while((i = iter.current())) { if(TQWidget * w = i->widget()) m_pDescriptor->actions()->append(new TQString(w->name())); ++iter; } } void KviCustomToolBar::childEvent(TQChildEvent *e) { if(KviActionManager::customizingToolBars()) { // this is useful for droppped and dragged-out children if(e->type() == TQEvent::ChildInserted) { if(e->child()->isWidgetType()) filterChild(TQT_TQOBJECT(e->child())); goto done; } if(e->type() == TQEvent::ChildRemoved) { if(e->child()->isWidgetType()) unfilterChild(TQT_TQOBJECT(e->child())); goto done; } } done: KviToolBar::childEvent(e); } void KviCustomToolBar::dragEnterEvent(TQDragEnterEvent *e) { if(!KviActionManager::customizingToolBars())return; KviActionManager::instance()->setCurrentToolBar(this); TQString text; if(TQTextDrag::decode(e,text)) { if(!text.isEmpty()) { KviAction * a = KviActionManager::instance()->getAction(text); if(a) { e->accept(true); int idx = dropIndexAt(mapFromGlobal(TQCursor::pos()),0,0); m_pDraggedChild = a->addToCustomToolBar(this); #ifdef COMPILE_USE_QT4 TQWidget * pWidgetToMove = widgetAt(idx); bool bDone = false; TQAction * a; if(pWidgetToMove) { a = actionForWidget(pWidgetToMove); if(a) { bDone = true; a = insertWidget(a,m_pDraggedChild); } } if(!bDone) a = addWidget(m_pDraggedChild); a->setVisible(true); #else boxLayout()->remove(m_pDraggedChild); // in case it was already added boxLayout()->insertWidget(idx,m_pDraggedChild); #ifdef COMPILE_TDE_SUPPORT // bleah :///// insertWidget(-1,m_pDraggedChild->sizeHint().width(),m_pDraggedChild,idx); #endif #endif TQEvent ev(TQEvent::LayoutHint); TQApplication::sendEvent(this,&ev); } else e->accept(false); } else e->accept(false); } else e->accept(false); } void KviCustomToolBar::dragMoveEvent(TQDragMoveEvent *e) { if(!m_pDraggedChild)return; drag(m_pDraggedChild,mapFromGlobal(TQCursor::pos())); } void KviCustomToolBar::dragLeaveEvent(TQDragLeaveEvent *e) { if(m_pDraggedChild) { if(m_pFilteredChildren) m_pFilteredChildren->remove(m_pDraggedChild); // just to be sure delete m_pDraggedChild; m_pDraggedChild = 0; } } void KviCustomToolBar::dropEvent(TQDropEvent *e) { if(!m_pDraggedChild)return; m_pDraggedChild = 0; e->accept(); // nuthin :) } int KviCustomToolBar::dropIndexAt(const TQPoint &pnt,TQWidget * exclude,int * excludeIdx) { // find the widget at the current poisition // treating exclude as if it was going to be removed // find also the exclude index if needed #ifdef COMPILE_USE_QT4 TQLayout * l = layout(); #else TQBoxLayout * l = boxLayout(); #endif TQLayoutItem * i = 0; if(excludeIdx)*excludeIdx = -1; int idx = 0; if(!l)return 0; TQLayoutIterator it = l->iterator(); // find the children with minimum distance int iMinDistIdx = -1; TQWidget * pMinDistW = 0; unsigned int uMinDist = 0xffffffff; int iExcludeIdx = -1; TQPoint pntExclude; TQWidget * w = 0; while((i = it.current())) { if((w = i->widget())) { if(uMinDist != 0) { int iRight = w->x() + w->width(); int iBottom = w->y() + w->height(); if((pnt.x() >= w->x()) && (pnt.y() >= w->y()) && (pnt.x() <= iRight) && (pnt.y() <= iBottom)) { // inside the widget // distance 0 pMinDistW = w; iMinDistIdx = idx; uMinDist = 0; } else { // outside the widget // compute the distance unsigned int uXDist = (pnt.x() < w->x()) ? (w->x() - pnt.x()) : (pnt.x() > iRight ? (pnt.x() - iRight) : 0); unsigned int uYDist = (pnt.y() < w->y()) ? (w->y() - pnt.y()) : (pnt.y() > iBottom ? (pnt.y() - iBottom) : 0); if((uXDist < 8192) && (uYDist < 8192)) { // it is in reasonable rect unsigned int uDist = (uXDist * uXDist) + (uYDist * uYDist); if(uDist < uMinDist) { // min distance for now uMinDist = uDist; pMinDistW = w; iMinDistIdx = idx; } } // else the user has a really HUUUGE screen } } // else the minimum distance widget has already been found if(w == exclude) { iExcludeIdx = idx; pntExclude = w->pos(); } } idx++; ++it; } if(!pMinDistW) { // ops.. not found at all (empty toolbar or really far from any button) if(orientation() == Qt::Horizontal) { if(pnt.x() < (width() / 2))iMinDistIdx = 0; // insert at position 0 else iMinDistIdx = idx; // else insert at the last position found } else { if(pnt.y() < (height() / 2))iMinDistIdx = 0; // insert at position 0 else iMinDistIdx = idx; // else insert at the last position found } } else { // got it, check for the exclude idx if((iExcludeIdx == -1) || (iExcludeIdx != iMinDistIdx)) { // would not put it over exclude idx // check if we have to stay on right or left of the widget found if(orientation() == Qt::Horizontal) { if(pnt.x() > (pMinDistW->x() + (pMinDistW->width() / 2))) iMinDistIdx++; // need to put it on the right } else { if(pnt.y() > (pMinDistW->y() + (pMinDistW->height() / 2))) iMinDistIdx++; // need to put it below } } // ok , check again (we might have moved exactly over exclude idx now!) if((iExcludeIdx != -1) && (iExcludeIdx != iMinDistIdx)) { // got the exclude idx by the way and wouldn't put exactly over it // check if exclude idx is "before" the current possible insert position // if it is , then lower down the index by one if(orientation() == Qt::Horizontal) { if(pnt.x() > pntExclude.x()) iMinDistIdx--; // removing exclude will move everything one step back } else { if(pnt.y() > pntExclude.y()) iMinDistIdx--; // removing exclude will move everything one step back } } } if(iMinDistIdx < 0)iMinDistIdx = 0; if(excludeIdx)*excludeIdx = iExcludeIdx; return iMinDistIdx; } #ifdef COMPILE_USE_QT4 TQWidget * KviCustomToolBar::widgetAt(int index) { TQLayout * l = layout(); if(!l) return NULL; TQLayoutItem * it = l->itemAt(index); if(!it) return NULL; return it->widget(); } TQAction * KviCustomToolBar::actionForWidget(TQWidget * pWidget) { return actionAt(pWidget->x() + 1,pWidget->y() + 1); } #endif void KviCustomToolBar::drag(TQWidget * child,const TQPoint &pnt) { int me = -1; int idx = dropIndexAt(pnt,child,&me); tqDebug("DROP INDEX IS %d, ME IS %d",idx,me); if(idx == me) return; // would move over itself #ifdef COMPILE_USE_QT4 TQWidget * pWidgetToMove = widgetAt(idx > me ? idx-1 : idx); tqDebug("SEARCHING FOR WIDGET TO MOVE AT %d AND FOUND %x (ME=%x)",idx > me ? idx-1 : idx,pWidgetToMove,child); if(pWidgetToMove == child) return; // hmmm bool bDone = false; TQAction * pMyOwnAction = actionForWidget(child); if(!pMyOwnAction) return; TQAction * a; removeAction(pMyOwnAction); if(pWidgetToMove) { a = actionForWidget(pWidgetToMove); if(a) { tqDebug("AND GOT ACTION FOR THAT WIDGET"); bDone = true; a = insertWidget(a,child); } } else { addAction(a); } if(!bDone) a = addWidget(child); a->setVisible(true); #else boxLayout()->remove(child); boxLayout()->insertWidget(idx,child); #ifdef COMPILE_TDE_SUPPORT // bleah :///// insertWidget(-1,child->width(),child,idx); #endif #endif TQEvent ev(TQEvent::LayoutHint); TQApplication::sendEvent(this,&ev); } void KviCustomToolBar::mousePressEvent(TQMouseEvent * e) { if(KviActionManager::customizingToolBars()) KviActionManager::instance()->setCurrentToolBar(this); KviToolBar::mousePressEvent(e); } bool KviCustomToolBar::eventFilter(TQObject *o,TQEvent *e) { if(!KviActionManager::customizingToolBars())goto unhandled; // anything here is done when customizing only if(e->type() == TQEvent::Enter) { if(m_pMovedChild)return true; // kill it while moving other children } if(e->type() == TQEvent::Leave) { if(m_pMovedChild)return true; // kill it while moving other children } if(e->type() == TQEvent::MouseButtonPress) { KviActionManager::instance()->setCurrentToolBar(this); TQMouseEvent * ev = (TQMouseEvent *)e; if(ev->button() & Qt::LeftButton) { if(o->isWidgetType()) { if(!( o->inherits("KviTalPopupMenu") || o->inherits("TQToolBarHandle") || o->inherits(TQDOCKWINDOWHANDLE_OBJECT_NAME_STRING) || o->inherits("TQDockWindowResizeHandle") || o->inherits("TQToolBarExtensionWidget") )) { m_pMovedChild = (TQWidget *)o; // allow resizing of children // FIXME: do it only if the child is really resizable if(m_pMovedChild->width() > 20) // might be an applet { if(ev->pos().x() > (m_pMovedChild->width() - 4)) { m_pMovedChild = 0; goto unhandled; // let the applet handle the event it } } g_pApp->setOverrideCursor(TQt::sizeAllCursor); return true; } } } goto unhandled; } if(e->type() == TQEvent::MouseButtonRelease) { if(m_pMovedChild) { g_pApp->restoreOverrideCursor(); m_pMovedChild = 0; return true; } goto unhandled; } if(e->type() == TQEvent::MouseMove) { if(m_pMovedChild) { TQMouseEvent * ev = (TQMouseEvent *)e; TQPoint pnt = mapFromGlobal(m_pMovedChild->mapToGlobal(ev->pos())); if((pnt.y() < 0) || (pnt.y() > height()) || (pnt.x() < 0) || (pnt.x() > width())) { // drag out! // FIXME: This is screwed up in TQt4.... :/ #ifdef COMPILE_USE_QT4 TQDrag * d = new TQDrag(this); TQMimeData * m = new TQMimeData(); m->setText(m_pMovedChild->name()); d->setMimeData(m); #else TQDragObject * d = new TQTextDrag(m_pMovedChild->name(),this); #endif KviAction * act = KviActionManager::instance()->getAction(m_pMovedChild->name()); if(act) { TQPixmap * pixie = act->bigIcon(); #ifdef COMPILE_USE_QT4 if(pixie) { d->setPixmap(*pixie); d->setHotSpot(TQPoint(3,3)); } #else if(pixie)d->setPixmap(*pixie,TQPoint(3,3)); #endif } //d->setPixmap(TQPixmap::grabWidget(m_pMovedChild),TQPoint(m_pMovedChild->width() / 2,m_pMovedChild->height() / 2)); // throw it somewhere else for now if(m_pFilteredChildren) unfilterChild(TQT_TQOBJECT(m_pMovedChild)); #ifdef COMPILE_USE_QT4 TQAction * pActionForMovedChild = actionForWidget(m_pMovedChild); if(pActionForMovedChild) pActionForMovedChild->setVisible(false); m_pMovedChild->hide(); #else m_pMovedChild->hide(); m_pMovedChild->reparent(g_pFrame,TQPoint(-1000,-1000),false); #endif TQEvent ev(TQEvent::LayoutHint); TQApplication::sendEvent(this,&ev); #ifdef COMPILE_USE_QT4 if(!d->exec(TQt::MoveAction) != TQt::MoveAction) #else if(!d->dragMove()) #endif { // the user has probably failed to remove the action from the toolbar // flash the trashcan in the customize toolbars dialog KviActionManager::instance()->emitRemoveActionsHintRequest(); // will filter it as ChildInserted #ifndef COMPILE_USE_QT4 m_pMovedChild->reparent(this,TQPoint(0,0),false); #endif #ifdef COMPILE_USE_QT4 TQAction * pActionForMovedChild = actionForWidget(m_pMovedChild); if(pActionForMovedChild) pActionForMovedChild->setVisible(false); #else boxLayout()->insertWidget(0,m_pMovedChild); m_pMovedChild->show(); #ifdef COMPILE_TDE_SUPPORT // bleah :///// insertWidget(-1,m_pMovedChild->width(),m_pMovedChild,0); #endif #endif TQEvent ev(TQEvent::LayoutHint); TQApplication::sendEvent(this,&ev); } else { TQApplication::sendPostedEvents(m_pMovedChild,0); m_pMovedChild->deleteLater(); m_pMovedChild = 0; } return true; } drag(m_pMovedChild,pnt); return true; } goto unhandled; } unhandled: return KviToolBar::eventFilter(o,e); }