From dcde5f12c9a3ad71dc1ac93dc21b125cda10ea65 Mon Sep 17 00:00:00 2001 From: Noldor Date: Mon, 16 Apr 2007 16:56:34 +0000 Subject: iakko's notifier (see changelog) git-svn-id: https://svn.kvirc.de/svn/trunk/kvirc@495 17fca916-40b9-46aa-a4ea-0a15b648b75c --- src/modules/notifier/notifierwindowtabs.cpp | 1473 +++++++++++++-------------- 1 file changed, 701 insertions(+), 772 deletions(-) (limited to 'src/modules/notifier/notifierwindowtabs.cpp') diff --git a/src/modules/notifier/notifierwindowtabs.cpp b/src/modules/notifier/notifierwindowtabs.cpp index 21c1e0dfe..18109339c 100644 --- a/src/modules/notifier/notifierwindowtabs.cpp +++ b/src/modules/notifier/notifierwindowtabs.cpp @@ -1,772 +1,701 @@ -//============================================================================= -// -// File : kvinotifierwindowtabs.cpp -// Created on dom 02 gen 2005 15:30:50 by Iacopo Palazzi -// -// This file is part of the KVIrc irc client distribution -// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it > -// -// 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. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -//============================================================================= - -#include "kvi_app.h" -#include "kvi_config.h" -#include "kvi_qstring.h" -#include "kvi_iconmanager.h" -#include "kvi_locale.h" -#include "kvi_options.h" -#include "kvi_window.h" - -#include -#include -#include -#include -#include - -#include "notifiermessage.h" -#include "notifierwindowtabs.h" - -extern KviNotifierWindow * g_pNotifierWindow; -KviNotifierWindowTabs * g_pTabs; - - -// --- tab object definition class - -KviNotifierWindowTab::KviNotifierWindowTab(KviWindow * pWnd, QString label) -{ - m_pWnd = pWnd; - m_label = label; - m_pMessageList = new KviPtrList; - m_pMessageList->setAutoDelete(true); - m_bFocused = false; - m_pCurrentMessage = 0; - - KviStr buffer; - g_pApp->getReadOnlyConfigPath(buffer,"libkvinotifier.kvc",KviApp::ConfigPlugins,true); - KviConfig cfg(buffer.ptr(),KviConfig::Read); - cfg.setGroup("NotifierSkin"); - m_clrHighlightedLabel = cfg.readColorEntry("HighlightedTabLablerColor",QColor(255,0,0)); - m_clrNormalLabel = cfg.readColorEntry("NormalTabLablerColor",QColor(0,0,0)); - m_clrChangedLabel = cfg.readColorEntry("ChangedTabLablerColor",QColor(0,0,100)); - - if(pWnd) - { - connect(pWnd,SIGNAL(windowNameChanged()),this,SLOT(labelChanged())); - connect(pWnd,SIGNAL(destroyed()),this,SLOT(closeMe())); - } -} - -KviNotifierWindowTab::~KviNotifierWindowTab() -{ - delete m_pMessageList; -} - -void KviNotifierWindowTab::setNextMessageAsCurrent() -{ - if(!m_pCurrentMessage)return; - m_pMessageList->findRef(m_pCurrentMessage); - m_pCurrentMessage = m_pMessageList->next(); - if(!m_pCurrentMessage)m_pCurrentMessage = m_pMessageList->last(); -} - -void KviNotifierWindowTab::setPrevMessageAsCurrent() -{ - if(!m_pCurrentMessage)return; - m_pMessageList->findRef(m_pCurrentMessage); - m_pCurrentMessage = m_pMessageList->prev(); - if(!m_pCurrentMessage)m_pCurrentMessage = m_pMessageList->first(); -} - -void KviNotifierWindowTab::setLastMessageAsCurrent() -{ - m_pCurrentMessage = m_pMessageList->last(); -} - -void KviNotifierWindowTab::appendMessage(KviNotifierMessage * m) -{ - if(m_pCurrentMessage == m_pMessageList->last())m_pCurrentMessage = m; - m_pMessageList->append(m); - // avoid having too much messages floating around - while(m_pMessageList->count() > MAX_MESSAGES_IN_WINDOW) - { - m = m_pMessageList->first(); - m_pMessageList->removeFirst(); - if(m == m_pCurrentMessage) - m_pCurrentMessage = m_pMessageList->first(); - } - if(focused())setState(Normal); - else setState(Highlighted); -} - -void KviNotifierWindowTab::labelChanged() -{ - if(!m_pWnd)return; - m_label = m_pWnd->windowName(); - setState(Changed); - g_pTabs->needToRedraw(); - g_pNotifierWindow->update(); -} - -void KviNotifierWindowTab::closeMe() -{ - g_pTabs->closeTab(this); -} - -void KviNotifierWindowTab::setFocused(bool b) -{ - m_bFocused = b; - if(m_bFocused)setState(Normal); -} - -void KviNotifierWindowTab::setState(TabState state) -{ - m_eState=state; - switch (m_eState) { - case Normal: - m_cLabel = m_clrNormalLabel; - break; - case Highlighted: - m_cLabel = m_clrHighlightedLabel; - break; - case Changed: - m_cLabel = m_clrChangedLabel; - break; - } -}; - -int KviNotifierWindowTab::width(bool b) { - int width = 0; - QFont * font; - - - if (focused()) { - font = g_pTabs->fontFocused(); - } else { - font = g_pTabs->fontUnfocused(); - } - - QFontMetrics fm(*font); - width = fm.width(label())+8; - - return width; -} - -// ##################################################################################à -// ### end of tab object definition class -// ##################################################################################à - - -KviNotifierWindowTabs::KviNotifierWindowTabs(QRect r,KviNotifierWindow * wnd) -:m_pWindow(wnd) -{ - g_pTabs = this; - m_pPixmap = new QPixmap(); - m_pPainter = new QPainter(); - m_pTabFocused = 0; - m_pWndTabFocused = 0; - m_iTabToStartFrom = 0; - - m_tabPtrList.clear(); - - loadImages(); - initConfig(); - resize(r); - m_pLastTab = 0; -} - -KviNotifierWindowTabs::~KviNotifierWindowTabs() -{ - QMap::Iterator tab; - for(tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ ) - delete tab.data(); - m_tabMap.clear(); - delete m_pFocusedFont; - delete m_pUnfocusedFont; - delete m_pPainter; - delete m_pPixmap; -} - -void KviNotifierWindowTabs::initConfig() -{ - KviStr buffer; - g_pApp->getReadOnlyConfigPath(buffer,"libkvinotifier.kvc",KviApp::ConfigPlugins,true); - - KviConfig cfg(buffer.ptr(),KviConfig::Read); - - cfg.setGroup("NotifierSkin"); - - QString szFamily = cfg.readEntry("TextFontFocusedTab","Arial"); - m_pFocusedFont = new QFont(szFamily,cfg.readIntEntry("TextFocusedFontSize",9)); - m_pFocusedFont->setItalic(true); - m_pFocusedFont->setBold(true); - szFamily = cfg.readEntry("TextFontUnfocusedTab","Arial"); - m_pUnfocusedFont = new QFont(szFamily,cfg.readIntEntry("TextUnfocusedFontSize",9)); - m_pUnfocusedFont->setItalic(true); -} - -void KviNotifierWindowTabs::loadImages() -{ - QPixmap * p; - if((p = g_pIconManager->getPixmap("notifier_right.png"))) - m_pixIconTabNext = *p; - - if((p = g_pIconManager->getPixmap("notifier_left.png"))) - m_pixIconTabPrev = *p; - - if((p = g_pIconManager->getPixmap("notifier_close.png"))) - m_pixIconCloseTab = *p; - - m_closeTabIconState = WDG_ICON_OFF; - -} - - - -void KviNotifierWindowTabs::addMessage(KviWindow * pWnd, KviNotifierMessage * message) -{ - QString sender = pWnd ? pWnd->windowName() : "----"; - - // Qui servirebbe anche una lista... perche' quando si inserisce - // un tab lui lo piazza dove gli pare nell'ordine - // e quindi iterando i tab nuovi possono trovarsi PRIMA dei tab vecchi - // il che' confonde un po - KviNotifierWindowTab * tab; - if (!m_tabMap.contains(pWnd)) { - m_tabMap.insert(pWnd, tab = new KviNotifierWindowTab(pWnd, sender)); - m_tabPtrList.append(tab); - } else { - tab = m_tabMap[pWnd]; - } - - tab->appendMessage(message); - - setFocusOn(tab); - if((g_pNotifierWindow->state()==Hidden) || (!m_pTabFocused)) - { -// setFocusOn(tab); - } else { - needToRedraw(); - } -} - -void KviNotifierWindowTabs::resize(QRect r) -{ - m_rct.setX(r.x()); - m_rct.setY(r.y()); - m_rct.setHeight(r.height()); - setWidth(r.width()); - - recalculatePositions(); -} - -void KviNotifierWindowTabs::setWidth(int w) { - m_rct.setWidth(w); - recalculatePositions(); -} - -void KviNotifierWindowTabs::recalculatePositions() -{ - m_rctCloseTabIcon.setX(m_rct.x()+m_rct.width()-m_pixIconCloseTab.width()); - m_rctCloseTabIcon.setY(m_rct.y()); - m_rctCloseTabIcon.setWidth(m_pixIconCloseTab.width()); - m_rctCloseTabIcon.setHeight(m_pixIconCloseTab.height()); - // The sensible area for the Close Icon - m_rctCloseTabIconHotArea = m_rctCloseTabIcon; - - if (m_bIsOverRightBound) { - m_rctNextIcon.setX(m_rct.x() + m_rct.width() - m_rctCloseTabIcon.width() - m_pixIconTabNext.width()); - m_rctNextIcon.setY(m_rct.y()); - m_rctNextIcon.setWidth(m_pixIconTabNext.width()); - m_rctNextIcon.setHeight(m_pixIconTabNext.height()); - } - - if (m_bIsOverLeftBound) { - m_rctPrevIcon.setX(m_rct.x()); - m_rctPrevIcon.setY(m_rct.y()); - m_rctPrevIcon.setWidth(m_pixIconTabPrev.width()); - m_rctPrevIcon.setHeight(m_pixIconTabPrev.height()); - } - - int tmpX, tmpWidth; - - tmpWidth = m_rctCloseTabIcon.x() - m_rct.x(); - - if (m_bIsOverRightBound) { - tmpWidth -= m_rctNextIcon.width(); - } - - if (m_bIsOverLeftBound) { - tmpWidth -= m_rctPrevIcon.width(); - tmpX = m_rct.x() + m_rctPrevIcon.width(); - } else { - tmpX = m_rct.x(); - } - - m_rctTabs.setX(tmpX); - m_rctTabs.setY(m_rct.y()); - - m_rctTabs.setWidth(tmpWidth); - m_rctTabs.setHeight(m_rct.height()); - - needToRedraw(); -} - -void KviNotifierWindowTabs::prev() -{ - if(!m_pTabFocused)return; - - KviNotifierWindowTab * tab; - KviPtrListIterator tabIterator (m_tabPtrList); - - tab = m_tabMap[m_pTabFocused->wnd()]; - tabIterator.atFirst(); - while ((tabIterator.current()) != tab) { - ++tabIterator; - } - - if (!tabIterator.atFirst()) { - --tabIterator; - tab = tabIterator.current(); - setFocusOn(tab); - } - -} - -void KviNotifierWindowTabs::next() -{ - if(!m_pTabFocused)return; - - KviNotifierWindowTab * tab; - KviPtrListIterator tabIterator (m_tabPtrList); - - tab = m_tabMap[m_pTabFocused->wnd()]; - tabIterator.atFirst(); - while ((tabIterator.current()) != tab) { - ++tabIterator; - } - - if (!tabIterator.atLast()) { - ++tabIterator; - tab = tabIterator.current(); - setFocusOn(tab); - } - -} - -void KviNotifierWindowTabs::mousePressEvent(QMouseEvent * e) { - - if (m_bIsOverRightBound && m_rctNextIcon.contains(e->pos())) { - return; - } - - if (m_bIsOverLeftBound && m_rctPrevIcon.contains(e->pos())) { - return; - } - - if(m_rctTabs.contains(e->pos())) - { - QMap::Iterator tab; - for (tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ ) { - if (tab.data()->rect().contains(e->pos())) { - if(g_pNotifierWindow->shiftPressed()) - closeTab(tab.data()); - else - setFocusOn(tab.data()); - return; - } - } - } - - if (m_rctCloseTabIconHotArea.contains(e->pos())) { - setCloseTabIcon(WDG_ICON_CLICKED); - return; - } - -} -void KviNotifierWindowTabs::leaveEvent() -{ - if(m_pLastTab) { - g_pNotifierWindow->update(); - m_bNeedToRedraw = true; - m_pLastTab = 0; - } -} - - -void KviNotifierWindowTabs::mouseMoveEvent(QMouseEvent * e) -{ - bool bInTab = false; - bool bNewTab = false; - if(m_rctTabs.contains(e->pos())) - { - QMap::Iterator tab; - for (tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ ) { - if (tab.data()->rect().contains(e->pos())) { - if(m_pLastTab != tab.data()) { - bNewTab = true; - m_pLastTab = tab.data(); - } - bInTab = true; - break; - } - } - } - - if(bInTab || m_rctCloseTabIconHotArea.contains(e->pos())) - { - g_pNotifierWindow->setCursor(Qt::PointingHandCursor); - } else { - g_pNotifierWindow->setCursor(Qt::ArrowCursor); - if(m_pLastTab) { - bNewTab = true; - m_pLastTab = 0; - } - } - if(bNewTab) { - g_pNotifierWindow->update(); - m_bNeedToRedraw = true; - } -} - -void KviNotifierWindowTabs::mouseReleaseEvent(QMouseEvent * e) -{ - - if (m_bIsOverRightBound && m_rctNextIcon.contains(e->pos())) { - scrollTabsLeft(); - return; - } - - if (m_bIsOverLeftBound && m_rctPrevIcon.contains(e->pos())) { - scrollTabsRight(); - return; - } - - if(currentTab()) - { - if (rctCloseTabIconHotArea().contains(e->pos())) - { - g_pNotifierWindow->close(); - g_pNotifierWindow->update(); - } - } - -} - -void KviNotifierWindowTabs::scrollTabsLeft() { - if (m_bIsOverRightBound) { - m_iTabToStartFrom++; - } - needToRedraw(); - g_pNotifierWindow->update(); -}; - -void KviNotifierWindowTabs::scrollTabsRight() { - if (m_bIsOverLeftBound) { - m_iTabToStartFrom--; - } - needToRedraw(); - g_pNotifierWindow->update(); -}; - -void KviNotifierWindowTabs::setCloseTabIcon(int state) { - -} - -void KviNotifierWindowTabs::resetIcons() -{ - setCloseTabIcon(WDG_ICON_OFF); -} - -void KviNotifierWindowTabs::setFocusOn(KviNotifierWindowTab * tab) -{ - if(m_pTabFocused)m_pTabFocused->setFocused(false); - m_pTabFocused = tab; - if(m_pTabFocused)m_pTabFocused->setFocused(); - - if (m_lastVisitedTabPtrList.containsRef(tab)) { - m_lastVisitedTabPtrList.removeRef(tab); - } - - m_lastVisitedTabPtrList.insert(0, tab); - - //scrollTabsRight(); - - KviPtrListIterator tabIterator (m_tabPtrList); - - - tabIterator.toFirst(); - - int i = 0; - while(m_iTabToStartFrom!=i) { - if(tabIterator.current()==m_pTabFocused) - { - m_iTabToStartFrom=i; - break; - } - i++; - ++tabIterator; - } - int iWidth = 0; - KviPtrListIterator startIterator (m_tabPtrList); - - i=0; - while(m_iTabToStartFrom!=i) { - i++; - ++startIterator; - } - - KviNotifierWindowTab * pTab = tabIterator.current(); - while ( pTab ) - { - iWidth+=pTab->width(); - while(iWidth>=m_rctTabs.width()) - { - m_iTabToStartFrom++; - iWidth-=startIterator.current()->width(); - ++startIterator; - } - - if(pTab == m_pTabFocused ) break; - - ++tabIterator; - pTab = tabIterator.current(); - } - - needToRedraw(); - - g_pNotifierWindow->update(); -} - -void KviNotifierWindowTabs::contextPopup(KviTalPopupMenu *pPopup,const QPoint& pos) -{ - if(m_rctTabs.contains(pos)) - { - int i=0; - QMap::Iterator tab; - for (tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ ) { - if (tab.data()->rect().contains(pos)) { - int id = pPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)),__tr2qs_ctx("Close tab","notifier"),g_pNotifierWindow,SLOT(hideTab(int))); - pPopup->setItemParameter(id,i); - } - i++; - } - } -} - -void KviNotifierWindowTabs::draw(QPainter * p) -{ - if(!m_bNeedToRedraw)return; - - - m_pPixmap->resize(m_rct.width(), m_rct.height()); - - m_pPainter->begin(m_pPixmap); - bitBlt(m_pPixmap,0,0,m_pWindow->background(),m_rct.x(), m_rct.y()); - - QFont tmpFont; - tmpFont = p->font(); - - m_pPainter->setFont(tmpFont); - - QString str; - - bool isBigger = false; - - int offset = 0; - - int closeIcon_X = m_rct.width() - m_rctCloseTabIcon.width(); - int nextIcon_X = closeIcon_X - m_pixIconTabNext.width(); - int prevIcon_X = m_rct.x(); - - int tmpTabsWidth = 0; - - KviPtrListIterator tabIterator (m_tabPtrList); - - //m_tabPtrList.findRef(m_tabMap[m_pTabFocused->wnd()]); - -// QMap::Iterator tab; - KviNotifierWindowTab * tab; - //for (tab = m_tabMap.begin(); tab != m_tabMap.end() && !isBigger; tab++ ) - tabIterator.toFirst(); - - int i = 0; - while(m_iTabToStartFrom!=i) { - i++; - ++tabIterator; - } - - if (m_iTabToStartFrom) { - // Draw the left arrow for more tabs - m_bIsOverLeftBound = true; - m_pPainter->drawPixmap(0, 0, m_pixIconTabPrev); - m_rctPrevIcon = QRect(m_rct.x(),m_rct.y(),m_pixIconTabPrev.width(),m_pixIconTabPrev.height()); - offset = m_pixIconTabPrev.width(); - } else { - m_bIsOverLeftBound = false; - } - - while ( (tab = tabIterator.current()) != 0) - { - ++tabIterator; - - isBigger = ( offset+4+tab->width() > m_rctTabs.width()); - if(isBigger) break; - if (tab->focused()) { - - m_pPainter->setFont(*m_pFocusedFont); - - tab->setRect(offset + m_rct.y(), m_rct.y(), tab->width(), - m_rctTabs.height()); - - QPen tmpP = m_pPainter->pen(); - - m_pPainter->setPen(QColor(143,154,202)); - - - if(tab == m_pLastTab) - { - QBrush tmpB = m_pPainter->brush(); - m_pPainter->setBrush(QColor(212,212,212)); - m_pPainter->drawRect(offset,0, tab->width(), - m_rctTabs.height()); - m_pPainter->setBrush(tmpB); - } else { - m_pPainter->drawRoundRect(offset,0, tab->width(), - m_rctTabs.height(),10); - } - - m_pPainter->setPen(tab->labelColor()); - m_pPainter->drawText(offset+4,m_rctTabs.height()-2,tab->label()); - m_pPainter->setPen(tmpP); - - offset += tab->width(); - - } else { - - m_pPainter->setFont(*m_pUnfocusedFont); - - tab->setRect(offset + m_rct.y(), m_rct.y(), tab->width(), - m_rctTabs.height() ); - QPen tmpP = m_pPainter->pen(); - - m_pPainter->setPen(QColor(212,212,212)); - - if(tab == m_pLastTab) - { - QBrush tmpB = m_pPainter->brush(); - m_pPainter->setBrush(QColor(212,212,212)); - m_pPainter->drawRect(offset,0, tab->width(), - m_rctTabs.height()); - m_pPainter->setBrush(tmpB); - } else - m_pPainter->drawRoundRect(offset,0, tab->width(), - m_rctTabs.height(),10); - - m_pPainter->setPen(tab->labelColor()); - m_pPainter->drawText(offset+4,m_rctTabs.height()-2,tab->label()); - - offset += tab->width()+2; - } - } - - if (isBigger) { - // Draw the right arrow for more tabs - m_bIsOverRightBound = true; - m_pPainter->drawPixmap(nextIcon_X, 0, m_pixIconTabNext); - m_rctNextIcon = QRect(m_rct.x()+nextIcon_X,m_rct.y(),m_pixIconTabNext.width(),m_pixIconTabNext.height()); - } else { - m_bIsOverRightBound = false; - } - - m_pPainter->drawPixmap(closeIcon_X, 0, m_pixIconCloseTab); - - m_pPainter->end(); - - p->drawPixmap(m_rct.x(), m_rct.y(), *m_pPixmap, 0, 0, m_pPixmap->width(), m_pPixmap->height()); - - m_bNeedToRedraw = false; - -} - -void KviNotifierWindowTabs::markAllMessagesAsHistoric() -{ - QMap::Iterator tab; - // Iterating every tab - for (tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ ) - { - // Setting all messages of the current tab as historic - // tab.data()->expireMessages(); - KviPtrList * tmpMessageList = tab.data()->messageList(); - for(KviNotifierMessage * m = tmpMessageList->last();m;m = tmpMessageList->prev()) { - if(m->historic())break; - m->setHistoric(); - } - } -} - -void KviNotifierWindowTabs::closeTab(KviWindow * pWnd) -{ - KviNotifierWindowTab * pTab = m_tabMap.find(pWnd).data(); - closeTab(pWnd, pTab); -} - -void KviNotifierWindowTabs::closeTab(KviNotifierWindowTab * pTab) -{ - KviWindow * pWnd = pTab->wnd(); - closeTab(pWnd, pTab); -} - -void KviNotifierWindowTabs::closeCurrentTab() -{ - // Paranoic checks... - if (!m_pTabFocused) return; // The current tab is null? Please, kill me... - KviNotifierWindowTab * pTab = m_pTabFocused; - if (m_tabMap.isEmpty()) return; // Empty??? The World is ending... - KviWindow * pWnd = pTab->wnd(); - if (!m_tabMap.contains(pWnd)) return; // The current tab is not on the map??? Call 911!! - // End paranoic stuff, go back to sanity... - - closeTab(pWnd, pTab); -} - -void KviNotifierWindowTabs::closeTab(KviWindow * pWnd, KviNotifierWindowTab * pTab) -{ - // Ok, we should be sure to delete the right tab... - m_tabPtrList.removeRef(pTab); - m_lastVisitedTabPtrList.removeRef(pTab); - m_tabMap.remove(pWnd); - delete pTab; - - if(m_tabMap.empty()) - { - m_pTabFocused = 0; - g_pNotifierWindow->showLineEdit(false); - g_pNotifierWindow->doHide(false); - } else { - - if (m_lastVisitedTabPtrList.count()) { - m_pTabFocused = m_lastVisitedTabPtrList.getFirst(); - } else { - m_pTabFocused = m_tabPtrList.getLast(); - } - - m_pTabFocused->setFocused(true); - } - m_bNeedToRedraw = true; - g_pNotifierWindow->update(); -} - -#include "m_notifierwindowtabs.moc" +//============================================================================= +// +// File : kvinotifierwindowtabs.cpp +// Created on dom 02 gen 2005 15:30:50 by Iacopo Palazzi +// +// This file is part of the KVIrc irc client distribution +// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it > +// +// 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. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +//============================================================================= + +#include "kvi_app.h" +#include "kvi_config.h" +#include "kvi_qstring.h" +#include "kvi_iconmanager.h" +#include "kvi_locale.h" +#include "kvi_options.h" +#include "kvi_window.h" + +#include +#include +#include +#include +#include + +#include "notifiermessage.h" +#include "notifierwindowtabs.h" + +extern KviNotifierWindow * g_pNotifierWindow; +KviNotifierWindowTabs * g_pTabs; + + +// --- tab object definition class + +KviNotifierWindowTab::KviNotifierWindowTab(KviWindow * pWnd, QString label) +{ + m_pWnd = pWnd; + m_label = label; + m_pMessageList = new KviPtrList; + m_pMessageList->setAutoDelete(true); + m_bFocused = false; + m_pCurrentMessage = 0; + + KviStr buffer; + g_pApp->getReadOnlyConfigPath(buffer,"libkvinotifier.kvc",KviApp::ConfigPlugins,true); + KviConfig cfg(buffer.ptr(),KviConfig::Read); + cfg.setGroup("NotifierSkin"); + m_clrHighlightedLabel = cfg.readColorEntry("HighlightedTabLablerColor",QColor(200,0,0)); + m_clrNormalLabel = cfg.readColorEntry("NormalTabLablerColor",QColor(0,0,0)); + m_clrChangedLabel = cfg.readColorEntry("ChangedTabLablerColor",QColor(0,0,100)); + + if(pWnd) + { + connect(pWnd,SIGNAL(windowNameChanged()),this,SLOT(labelChanged())); + connect(pWnd,SIGNAL(destroyed()),this,SLOT(closeMe())); + } +} + +KviNotifierWindowTab::~KviNotifierWindowTab() +{ + delete m_pMessageList; +} + +void KviNotifierWindowTab::setNextMessageAsCurrent() +{ + if(!m_pCurrentMessage)return; + m_pMessageList->findRef(m_pCurrentMessage); + m_pCurrentMessage = m_pMessageList->next(); + if(!m_pCurrentMessage)m_pCurrentMessage = m_pMessageList->last(); +} + +void KviNotifierWindowTab::setPrevMessageAsCurrent() +{ + if(!m_pCurrentMessage)return; + m_pMessageList->findRef(m_pCurrentMessage); + m_pCurrentMessage = m_pMessageList->prev(); + if(!m_pCurrentMessage)m_pCurrentMessage = m_pMessageList->first(); +} + +void KviNotifierWindowTab::setLastMessageAsCurrent() +{ + m_pCurrentMessage = m_pMessageList->last(); +} + +void KviNotifierWindowTab::appendMessage(KviNotifierMessage * m) +{ + if(m_pCurrentMessage == m_pMessageList->last())m_pCurrentMessage = m; + m_pMessageList->append(m); + // avoid having too much messages floating around + while(m_pMessageList->count() > MAX_MESSAGES_IN_WINDOW) + { + m = m_pMessageList->first(); + m_pMessageList->removeFirst(); + if(m == m_pCurrentMessage) + m_pCurrentMessage = m_pMessageList->first(); + } + if(focused())setState(Normal); + else setState(Highlighted); +} + +void KviNotifierWindowTab::labelChanged() +{ + if(!m_pWnd)return; + m_label = m_pWnd->windowName(); + setState(Changed); + g_pTabs->needToRedraw(); + g_pNotifierWindow->update(); +} + +void KviNotifierWindowTab::closeMe() +{ + g_pTabs->closeTab(this); +} + +void KviNotifierWindowTab::setFocused(bool b) +{ + m_bFocused = b; + if(m_bFocused)setState(Normal); +} + +void KviNotifierWindowTab::setState(TabState state) +{ + m_eState=state; + switch (m_eState) { + case Normal: + m_cLabel = m_clrNormalLabel; + break; + case Highlighted: + m_cLabel = m_clrHighlightedLabel; + break; + case Changed: + m_cLabel = m_clrChangedLabel; + break; + } +}; + +int KviNotifierWindowTab::width(bool b) { + int width = 0; + QFont * font; + + QPixmap * sx; + QPixmap * dx; + + if (focused()) { + font = g_pTabs->fontFocused(); + sx = g_pTabs->tabFocusedPixSx(); + dx = g_pTabs->tabFocusedPixSx(); + } else { + sx = g_pTabs->tabUnfocusedPixSx(); + dx = g_pTabs->tabUnfocusedPixSx(); + font = g_pTabs->fontUnfocused(); + } + + QFontMetrics fm(*font); + width = fm.width(label())+2; + if (!b) width += sx->width() + dx->width(); + + return width; +} + +// ##################################################################################à +// ### end of tab object definition class +// ##################################################################################à + + +KviNotifierWindowTabs::KviNotifierWindowTabs(QRect r) +{ + g_pTabs = this; + m_pPixmap = new QPixmap(); + m_pPainter = new QPainter(); + m_pTabFocused = 0; + m_pWndTabFocused = 0; + m_iTabToStartFrom = 0; + + m_tabPtrList.clear(); + + loadImages(); + initConfig(); + resize(r); +} + +KviNotifierWindowTabs::~KviNotifierWindowTabs() +{ + QMap::Iterator tab; + for(tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ ) + delete tab.data(); + m_tabMap.clear(); + delete m_pFocusedFont; + delete m_pUnfocusedFont; + delete m_pPainter; + delete m_pPixmap; +} + +void KviNotifierWindowTabs::initConfig() +{ + KviStr buffer; + g_pApp->getReadOnlyConfigPath(buffer,"libkvinotifier.kvc",KviApp::ConfigPlugins,true); + + KviConfig cfg(buffer.ptr(),KviConfig::Read); + + cfg.setGroup("NotifierSkin"); + + QString szFamily = cfg.readEntry("TextFontFocusedTab","Arial"); + m_pFocusedFont = new QFont(szFamily,cfg.readIntEntry("TextFocusedFontSize",10)); + m_pFocusedFont->setBold(true); + szFamily = cfg.readEntry("TextFontUnfocusedTab","Arial"); + m_pUnfocusedFont = new QFont(szFamily,cfg.readIntEntry("TextUnfocusedFontSize",9)); +} + +void KviNotifierWindowTabs::loadImages() +{ + QPixmap * p; + if((p = g_pIconManager->getPixmap("notifier_pix_tab_dx.png"))) + m_pixDX = *p; + if((p = g_pIconManager->getPixmap("notifier_pix_tab_sx.png"))) + m_pixSX = *p; + if((p = g_pIconManager->getPixmap("notifier_pix_tab_bkg.png"))) + m_pixBKG = *p; + if((p = g_pIconManager->getPixmap("notifier_pix_tab_focused_sx.png"))) + m_pixSXFocused = *p; + if((p = g_pIconManager->getPixmap("notifier_pix_tab_focused_dx.png"))) + m_pixDXFocused = *p; + if((p = g_pIconManager->getPixmap("notifier_pix_tab_focused_bkg.png"))) + m_pixBKGFocused = *p; + if((p = g_pIconManager->getPixmap("notifier_pix_tab_unfocused_sx.png"))) + m_pixSXUnfocused = *p; + if((p = g_pIconManager->getPixmap("notifier_pix_tab_unfocused_dx.png"))) + m_pixDXUnfocused = *p; + if((p = g_pIconManager->getPixmap("notifier_pix_tab_unfocused_bkg.png"))) + m_pixBKGUnfocused = *p; + + if((p = g_pIconManager->getPixmap("notifier_icon_tab_next_out.png"))) + m_pixIconTabNext_out = *p; + if((p = g_pIconManager->getPixmap("notifier_icon_tab_next_over.png"))) + m_pixIconTabNext_over = *p; + if((p = g_pIconManager->getPixmap("notifier_icon_tab_next_clicked.png"))) + m_pixIconTabNext_clicked = *p; + + m_pixIconTabNext = m_pixIconTabNext_out; + + if((p = g_pIconManager->getPixmap("notifier_icon_tab_prev_out.png"))) + m_pixIconTabPrev_out = *p; + if((p = g_pIconManager->getPixmap("notifier_icon_tab_prev_over.png"))) + m_pixIconTabPrev_over = *p; + if((p = g_pIconManager->getPixmap("notifier_icon_tab_prev_clicked.png"))) + m_pixIconTabPrev_clicked = *p; + + m_pixIconTabPrev = m_pixIconTabPrev_out; + + if((p = g_pIconManager->getPixmap("notifier_icon_tab_close_off.png"))) + m_pixIconCloseTab_off = *p; + if((p = g_pIconManager->getPixmap("notifier_icon_tab_close_on.png"))) + m_pixIconCloseTab_on = *p; + if((p = g_pIconManager->getPixmap("notifier_icon_tab_close_clicked.png"))) + m_pixIconCloseTab_clicked = *p; + + m_pixIconCloseTab = m_pixIconCloseTab_off; + + m_closeTabIconState = WDG_ICON_OFF; + +} + + + +void KviNotifierWindowTabs::addMessage(KviWindow * pWnd, KviNotifierMessage * message) +{ + QString sender = pWnd ? pWnd->windowName() : "----"; + + // Qui servirebbe anche una lista... perche' quando si inserisce + // un tab lui lo piazza dove gli pare nell'ordine + // e quindi iterando i tab nuovi possono trovarsi PRIMA dei tab vecchi + // il che' confonde un po + KviNotifierWindowTab * tab; + if (!m_tabMap.contains(pWnd)) { + m_tabMap.insert(pWnd, tab = new KviNotifierWindowTab(pWnd, sender)); + m_tabPtrList.append(tab); + } else { + tab = m_tabMap[pWnd]; + } + + tab->appendMessage(message); + + if((g_pNotifierWindow->state()==Hidden) || (!m_pTabFocused)) + { + setFocusOn(tab); + } else { + needToRedraw(); + } +} + +void KviNotifierWindowTabs::resize(QRect r) +{ + m_rct.setX(r.x()); + m_rct.setY(r.y()); + m_rct.setHeight(r.height()); + setWidth(r.width()); + + recalculatePositions(); +} + +void KviNotifierWindowTabs::setWidth(int w) { + m_rct.setWidth(w); + recalculatePositions(); +} + +void KviNotifierWindowTabs::recalculatePositions() +{ + m_rctCloseTabIcon.setX(m_rct.x()+m_rct.width()-m_pixIconCloseTab.width()); + m_rctCloseTabIcon.setY(m_rct.y()); + m_rctCloseTabIcon.setWidth(m_pixIconCloseTab.width()); + m_rctCloseTabIcon.setHeight(m_pixIconCloseTab.height()); + // The sensible area for the Close Icon + m_rctCloseTabIconHotArea.setX(m_rctCloseTabIcon.x()+6); + m_rctCloseTabIconHotArea.setY(m_rctCloseTabIcon.y()+3); + m_rctCloseTabIconHotArea.setWidth(16); + m_rctCloseTabIconHotArea.setHeight(16); + + if (m_bIsOverRightBound) { + m_rctNextIcon.setX(m_rct.x() + m_rct.width() - m_rctCloseTabIcon.width() - m_pixIconTabNext.width()); + m_rctNextIcon.setY(m_rct.y()); + m_rctNextIcon.setWidth(m_pixIconTabNext.width()); + m_rctNextIcon.setHeight(m_pixIconTabNext.height()); + } + + if (m_bIsOverLeftBound) { + m_rctPrevIcon.setX(m_rct.x()); + m_rctPrevIcon.setY(m_rct.y()); + m_rctPrevIcon.setWidth(m_pixIconTabPrev.width()); + m_rctPrevIcon.setHeight(m_pixIconTabPrev.height()); + } + + int tmpX, tmpWidth; + + tmpWidth = m_rctCloseTabIcon.x() - m_rct.x(); + + if (m_bIsOverRightBound) { + tmpWidth -= m_rctNextIcon.width(); + } + + if (m_bIsOverLeftBound) { + tmpWidth -= m_rctPrevIcon.width(); + tmpX = m_rct.x() + m_rctPrevIcon.width(); + } else { + tmpX = m_rct.x(); + } + + m_rctTabs.setX(tmpX); + m_rctTabs.setY(m_rct.y()); + + m_rctTabs.setWidth(tmpWidth); + m_rctTabs.setHeight(m_rct.height()); + + needToRedraw(); +} + +void KviNotifierWindowTabs::prev() +{ + if(!m_pTabFocused)return; + + KviNotifierWindowTab * tab; + QPtrListIterator tabIterator (m_tabPtrList); + + tab = m_tabMap[m_pTabFocused->wnd()]; + + tabIterator.atFirst(); + + while ((tabIterator.current()) != tab) { + ++tabIterator; + } + + if (!tabIterator.atFirst()) { + --tabIterator; + tab = tabIterator.current(); + setFocusOn(tab); + } + +} + +void KviNotifierWindowTabs::next() +{ + if(!m_pTabFocused)return; + + KviNotifierWindowTab * tab; + QPtrListIterator tabIterator (m_tabPtrList); + + tab = m_tabMap[m_pTabFocused->wnd()]; + tabIterator.atFirst(); + while ((tabIterator.current()) != tab) { + ++tabIterator; + } + + if (!tabIterator.atLast()) { + ++tabIterator; + tab = tabIterator.current(); + setFocusOn(tab); + } + +} + +void KviNotifierWindowTabs::mousePressEvent(QMouseEvent * e) { + + if (m_bIsOverRightBound && m_rctNextIcon.contains(e->pos())) { + return; + } + + if (m_bIsOverLeftBound && m_rctPrevIcon.contains(e->pos())) { + return; + } + + if(m_rctTabs.contains(e->pos())) + { + QMap::Iterator tab; + for (tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ ) { + if (tab.data()->rect().contains(e->pos())) { + setFocusOn(tab.data()); + return; + } + } + } + + if (m_rctCloseTabIconHotArea.contains(e->pos())) { + setCloseTabIcon(WDG_ICON_CLICKED); + return; + } + +} + +void KviNotifierWindowTabs::mouseMoveEvent(QMouseEvent * e) +{ + if (m_rctCloseTabIconHotArea.contains(e->pos())) + { + setCloseTabIcon(WDG_ICON_ON); + } else { + if (closeTabIconState()!=WDG_ICON_OFF) + setCloseTabIcon(WDG_ICON_OFF); + } +} + +void KviNotifierWindowTabs::mouseReleaseEvent(QMouseEvent * e) +{ + + if (m_bIsOverRightBound && m_rctNextIcon.contains(e->pos())) { + scrollTabsLeft(); + return; + } + + if (m_bIsOverLeftBound && m_rctPrevIcon.contains(e->pos())) { + scrollTabsRight(); + return; + } + + if(currentTab()) + { + if (rctCloseTabIconHotArea().contains(e->pos())) + { + closeCurrentTab(); + g_pNotifierWindow->update(); + } + } + +} + +void KviNotifierWindowTabs::scrollTabsLeft() { + if (m_bIsOverRightBound) { + m_iTabToStartFrom++; + } + needToRedraw(); + g_pNotifierWindow->update(); +}; + +void KviNotifierWindowTabs::scrollTabsRight() { + if (m_bIsOverLeftBound) { + m_iTabToStartFrom--; + } + needToRedraw(); + g_pNotifierWindow->update(); +}; + +void KviNotifierWindowTabs::setCloseTabIcon(int state) { + + //if (m_writeIconState==WDG_ICON_OFF && state!=WDG_ICON_OFF) + if (m_closeTabIconState!=state) { + switch (state) { + case WDG_ICON_ON: m_pixIconCloseTab = m_pixIconCloseTab_on; break; + case WDG_ICON_OFF: m_pixIconCloseTab = m_pixIconCloseTab_off; break; + case WDG_ICON_CLICKED: m_pixIconCloseTab = m_pixIconCloseTab_clicked; break; + } + needToRedraw(); + m_closeTabIconState = state; + } +} + +void KviNotifierWindowTabs::resetIcons() +{ + setCloseTabIcon(WDG_ICON_OFF); +} + +void KviNotifierWindowTabs::setFocusOn(KviNotifierWindowTab * tab) +{ + if(m_pTabFocused)m_pTabFocused->setFocused(false); + m_pTabFocused = tab; + if(m_pTabFocused)m_pTabFocused->setFocused(); + + if (m_lastVisitedTabPtrList.containsRef(tab)) { + m_lastVisitedTabPtrList.removeRef(tab); + } + + m_lastVisitedTabPtrList.insert(0, tab); + + needToRedraw(); + + g_pNotifierWindow->update(); +} + +void KviNotifierWindowTabs::draw(QPainter * p) +{ + if(!m_bNeedToRedraw)return; + + m_pPixmap->resize(m_rct.width(), m_rct.height()); + + m_pPainter->begin(m_pPixmap); + + QFont tmpFont; + tmpFont = p->font(); + + m_pPainter->setFont(tmpFont); + + QString str; + + bool isBigger = false; + + int offset = 0; + + int closeIcon_X = m_rct.width() - m_rctCloseTabIcon.width(); + int nextIcon_X = closeIcon_X - m_pixIconTabNext_out.width(); + int prevIcon_X = m_rct.x(); + + int tmpTabsWidth = 0; + + m_pPainter->drawPixmap(0,0,m_pixSX); + m_pPainter->drawPixmap(m_rct.width()-m_pixDX.width(),0,m_pixDX); + m_pPainter->drawTiledPixmap(m_pixSX.width(),0,m_rct.width()-m_pixSX.width()-m_pixDX.width(),m_rct.height(),m_pixBKG); + + QPtrListIterator tabIterator (m_tabPtrList); + + //m_tabPtrList.findRef(m_tabMap[m_pTabFocused->wnd()]); + +// QMap::Iterator tab; + KviNotifierWindowTab * tab; + //for (tab = m_tabMap.begin(); tab != m_tabMap.end() && !isBigger; tab++ ) + tabIterator.toFirst(); + + int i = 0; + while(m_iTabToStartFrom!=i) { + i++; + ++tabIterator; + } + + while ( ((tab = tabIterator.current()) != 0) && !isBigger) + { + ++tabIterator; + + if (tab->focused()) { + + m_pPainter->setFont(*m_pFocusedFont); + + tab->setRect(m_rct.x() + offset, m_rctTabs.y(), tab->width(), m_rctTabs.height()); + + m_pPainter->drawPixmap(offset,0,m_pixSXFocused); + m_pPainter->drawTiledPixmap(offset+m_pixSXFocused.width(),0,tab->width(true),m_rctTabs.height(),m_pixBKGFocused); + m_pPainter->drawPixmap(offset+m_pixSXFocused.width()+tab->width(true),0,m_pixDXFocused); + QPen tmpP = m_pPainter->pen(); m_pPainter->setPen(tab->labelColor()); + m_pPainter->drawText(offset+m_pixSXFocused.width()+1,m_rctTabs.height()-NTF_TABS_FONT_BASELINE,tab->label()); + m_pPainter->setPen(tmpP); + + offset += tab->width(); + + } else { + + m_pPainter->setFont(*m_pUnfocusedFont); + + tab->setRect(m_rct.x() + offset, m_rctTabs.y(), tab->width(), m_rctTabs.height()); + + m_pPainter->drawPixmap(offset, 0, m_pixSXUnfocused); + m_pPainter->drawTiledPixmap(offset+m_pixSXUnfocused.width(), 0, tab->width(true), m_rctTabs.height(), m_pixBKGUnfocused); + m_pPainter->drawPixmap(offset+m_pixSXUnfocused.width()+tab->width(true), 0, m_pixDXUnfocused); + QPen tmpP = m_pPainter->pen(); m_pPainter->setPen(tab->labelColor()); + m_pPainter->drawText(offset+m_pixSXUnfocused.width()+1,m_rctTabs.height()-NTF_TABS_FONT_BASELINE+1,tab->label()); + m_pPainter->setPen(tmpP); + offset += tab->width(); + } + + if (offset > m_rctTabs.width()) isBigger = true; else isBigger = false; + } + + if (m_iTabToStartFrom) { + // Draw the left arrow for more tabs + m_bIsOverLeftBound = true; + m_pPainter->drawPixmap(0, 0, m_pixIconTabPrev); + } else { + m_bIsOverLeftBound = false; + } + + if (isBigger) { + // Draw the right arrow for more tabs + m_bIsOverRightBound = true; + m_pPainter->drawPixmap(nextIcon_X, 0, m_pixIconTabNext); + } else { + m_bIsOverRightBound = false; + } + + m_pPainter->drawPixmap(closeIcon_X, 0, m_pixIconCloseTab); + + m_pPainter->end(); + + p->drawPixmap(m_rct.x(), m_rct.y(), *m_pPixmap, 0, 0, m_pPixmap->width(), m_pPixmap->height()); + + m_bNeedToRedraw = false; + +} + +void KviNotifierWindowTabs::markAllMessagesAsHistoric() +{ + QMap::Iterator tab; + // Iterating every tab + for (tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ ) + { + // Setting all messages of the current tab as historic + // tab.data()->expireMessages(); + KviPtrList * tmpMessageList = tab.data()->messageList(); + for(KviNotifierMessage * m = tmpMessageList->last();m;m = tmpMessageList->prev()) { + if(m->historic())break; + m->setHistoric(); + } + } +} + +void KviNotifierWindowTabs::closeTab(KviWindow * pWnd) +{ + KviNotifierWindowTab * pTab = m_tabMap.find(pWnd).data(); + closeTab(pWnd, pTab); +} + +void KviNotifierWindowTabs::closeTab(KviNotifierWindowTab * pTab) +{ + KviWindow * pWnd = pTab->wnd(); + closeTab(pWnd, pTab); +} + +void KviNotifierWindowTabs::closeCurrentTab() +{ + // Paranoic checks... + if (!m_pTabFocused) return; // The current tab is null? Please, kill me... + KviNotifierWindowTab * pTab = m_pTabFocused; + if (m_tabMap.isEmpty()) return; // Empty??? The World is ending... + KviWindow * pWnd = pTab->wnd(); + if (!m_tabMap.contains(pWnd)) return; // The current tab is not on the map??? Call 911!! + // End paranoic stuff, go back to sanity... + + closeTab(pWnd, pTab); +} + +void KviNotifierWindowTabs::closeTab(KviWindow * pWnd, KviNotifierWindowTab * pTab) +{ + // Ok, we should be sure to delete the right tab... + m_tabPtrList.removeRef(pTab); + m_lastVisitedTabPtrList.removeRef(pTab); + m_tabMap.remove(pWnd); + delete pTab; + + if(m_tabMap.empty()) + { + m_pTabFocused = 0; + g_pNotifierWindow->showLineEdit(false); + g_pNotifierWindow->doHide(false); + } else { + + if (m_lastVisitedTabPtrList.count()) { + m_pTabFocused = m_lastVisitedTabPtrList.getFirst(); + } else { + m_pTabFocused = m_tabPtrList.getLast(); + } + + m_pTabFocused->setFocused(true); + } +} + +#include "m_notifierwindowtabs.moc" -- cgit v1.3.1-10-gc9f91