akregator/src

tabwidget.cpp

00001 /*
00002     This file is part of Akregator.
00003 
00004     Copyright (C) 2004 Sashmit Bhaduri <smt@vfemail.net>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020     As a special exception, permission is given to link this program
00021     with any edition of Qt, and distribute the resulting executable,
00022     without including the source code for Qt in the source distribution.
00023 */
00024 
00025 #include "tabwidget.h"
00026 
00027 #include <qstyle.h>
00028 #include <qapplication.h>
00029 #include <qiconset.h>
00030 #include <qclipboard.h>
00031 #include <qmap.h>
00032 #include <qptrdict.h>
00033 #include <qstring.h>
00034 #include <qtoolbutton.h>
00035 #include <qtooltip.h>
00036 
00037 #include <kapplication.h>
00038 #include <kdebug.h>
00039 #include <ktabwidget.h>
00040 #include <ktabbar.h>
00041 #include <kpopupmenu.h>
00042 #include <krun.h>
00043 #include <klocale.h>
00044 #include <khtmlview.h>
00045 #include <khtml_part.h>
00046 #include <kiconloader.h>
00047 #include <kurl.h>
00048 #include <kurldrag.h>
00049 #include <kmimetype.h>
00050 
00051 #include "actionmanager.h"
00052 #include "frame.h"
00053 #include "akregatorconfig.h"
00054 
00055 namespace Akregator {
00056 
00057 class TabWidget::TabWidgetPrivate
00058 {
00059     public:
00060     QPtrDict<Frame> frames;
00061     uint CurrentMaxLength;
00062     QWidget* currentItem;
00063     QToolButton* tabsClose;
00064 };
00065 
00066 TabWidget::TabWidget(QWidget * parent, const char *name)
00067         :KTabWidget(parent, name), d(new TabWidgetPrivate)
00068 {
00069     d->CurrentMaxLength = 30;
00070     setMinimumSize(250,150);
00071     setTabReorderingEnabled(false);
00072     connect( this, SIGNAL( currentChanged(QWidget *) ), this,
00073             SLOT( slotTabChanged(QWidget *) ) );
00074     connect(this, SIGNAL(closeRequest(QWidget*)), this, SLOT(slotCloseRequest(QWidget*)));
00075     setHoverCloseButton(Settings::closeButtonOnTabs());
00076 
00077     d->tabsClose = new QToolButton(this);
00078     d->tabsClose->setAccel(QKeySequence("Ctrl+W"));
00079     connect( d->tabsClose, SIGNAL( clicked() ), this,
00080             SLOT( slotRemoveCurrentFrame() ) );
00081 
00082     d->tabsClose->setIconSet( SmallIconSet( "tab_remove" ) );
00083     d->tabsClose->adjustSize();
00084     QToolTip::add(d->tabsClose, i18n("Close the current tab"));
00085     setCornerWidget( d->tabsClose, TopRight );
00086 }
00087 
00088 TabWidget::~TabWidget()
00089 {
00090     delete d;
00091     d = 0;
00092 }
00093 
00094 void TabWidget::slotSettingsChanged()
00095 {
00096     if (hoverCloseButton() != Settings::closeButtonOnTabs())
00097         setHoverCloseButton(Settings::closeButtonOnTabs());
00098 }
00099 
00100 void TabWidget::slotNextTab()
00101 {
00102     setCurrentPage((currentPageIndex()+1) % count());
00103 }
00104 
00105 void TabWidget::slotPreviousTab()
00106 {
00107     if (currentPageIndex() == 0)
00108         setCurrentPage(count()-1);
00109     else
00110         setCurrentPage(currentPageIndex()-1);
00111 }
00112 
00113 void TabWidget::addFrame(Frame *f)
00114 {
00115     if (!f || !f->widget()) 
00116         return;
00117     d->frames.insert(f->widget(), f);
00118     addTab(f->widget(), f->title());
00119     connect(f, SIGNAL(titleChanged(Frame*, const QString& )), this, SLOT(slotSetTitle(Frame*, const QString& )));
00120     slotSetTitle(f, f->title());
00121 }
00122 
00123 Frame *TabWidget::currentFrame()
00124 {
00125     QWidget* w = currentPage();
00126     
00127     return w ? d->frames[w] : 0;
00128 }
00129 
00130 QPtrList<Frame> TabWidget::frames() const
00131 {
00132     QPtrList<Frame> result;
00133     QPtrDictIterator<Frame> it(d->frames);
00134     while (it.current())
00135     {
00136         result.append(it.current());
00137         ++it;
00138     }
00139 
00140     return result;
00141 }
00142 
00143 void TabWidget::slotTabChanged(QWidget *w)
00144 {
00145     // FIXME: Don't hardcode the tab position of main frame
00146     d->tabsClose->setDisabled(currentPageIndex() == 0);
00147     emit currentFrameChanged(d->frames[w]);
00148 }
00149 
00150 void TabWidget::slotRemoveCurrentFrame()
00151 {
00152     removeFrame(currentFrame());
00153 }
00154 
00155 void TabWidget::removeFrame(Frame *f)
00156 {
00157     f->setCompleted();
00158     d->frames.remove(f->widget());
00159     removePage(f->widget());
00160     delete f;
00161     setTitle( currentFrame()->title(), currentPage() );
00162 }
00163 
00164 // copied wholesale from KonqFrameTabs
00165 uint TabWidget::tabBarWidthForMaxChars( uint maxLength )
00166 {
00167     int hframe, overlap;
00168     hframe = tabBar()->style().pixelMetric( QStyle::PM_TabBarTabHSpace, this );
00169     overlap = tabBar()->style().pixelMetric( QStyle::PM_TabBarTabOverlap, this );
00170 
00171     QFontMetrics fm = tabBar()->fontMetrics();
00172     int x = 0;
00173     for( int i=0; i < count(); ++i ) {
00174         Frame *f=d->frames[page(i)];
00175         QString newTitle=f->title();
00176         if ( newTitle.length() > maxLength )
00177             newTitle = newTitle.left( maxLength-3 ) + "...";
00178 
00179         QTab* tab = tabBar()->tabAt( i );
00180         int lw = fm.width( newTitle );
00181         int iw = 0;
00182         if ( tab->iconSet() )
00183             iw = tab->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4;
00184 
00185         x += ( tabBar()->style().sizeFromContents( QStyle::CT_TabBarTab, this,                             QSize( QMAX( lw + hframe + iw, QApplication::globalStrut().width() ), 0 ), QStyleOption( tab ) ) ).width();
00186     }
00187     return x;
00188 }
00189 
00190 void TabWidget::slotSetTitle(Frame* frame, const QString& title)
00191 {
00192     setTitle(title, frame->widget());
00193 }
00194 
00195 void TabWidget::setTitle( const QString &title , QWidget* sender)
00196 {
00197     removeTabToolTip( sender );
00198    
00199     uint lcw=0, rcw=0;
00200     int tabBarHeight = tabBar()->sizeHint().height();
00201     if ( cornerWidget( TopLeft ) && cornerWidget( TopLeft )->isVisible() )
00202         lcw = QMAX( cornerWidget( TopLeft )->width(), tabBarHeight );
00203     if ( cornerWidget( TopRight ) && cornerWidget( TopRight )->isVisible() )
00204         rcw = QMAX( cornerWidget( TopRight )->width(), tabBarHeight );
00205     uint maxTabBarWidth = width() - lcw - rcw;
00206 
00207     uint newMaxLength=30;
00208     for ( ; newMaxLength > 3; newMaxLength-- ) 
00209 {
00210         if ( tabBarWidthForMaxChars( newMaxLength ) < maxTabBarWidth )
00211             break;
00212     }
00213     QString newTitle = title;
00214     if ( newTitle.length() > newMaxLength )
00215     {
00216         setTabToolTip( sender, newTitle );
00217         newTitle = newTitle.left( newMaxLength-3 ) + "...";
00218     }
00219 
00220     newTitle.replace( '&', "&&" );
00221     if ( tabLabel( sender ) != newTitle )
00222         changeTab( sender, newTitle );
00223 
00224     if( newMaxLength != d->CurrentMaxLength )
00225     {
00226         for( int i = 0; i < count(); ++i)
00227         {
00228             Frame *f=d->frames[page(i)];
00229             newTitle=f->title();
00230             removeTabToolTip( page( i ) );
00231             if ( newTitle.length() > newMaxLength )
00232             {
00233                 setTabToolTip( page( i ), newTitle );
00234                 newTitle = newTitle.left( newMaxLength-3 ) + "...";
00235             }
00236 
00237             newTitle.replace( '&', "&&" );
00238             if ( newTitle != tabLabel( page( i ) ) )
00239                     changeTab( page( i ), newTitle );
00240         }
00241         d->CurrentMaxLength = newMaxLength;
00242     }
00243 }
00244 
00245 void TabWidget::contextMenu(int i, const QPoint &p)
00246 {
00247     QWidget* w = ActionManager::getInstance()->container("tab_popup");
00248     d->currentItem = page(i);
00249     //kdDebug() << indexOf(d->currentItem) << endl;
00250     if (w && indexOf(d->currentItem) != 0)
00251         static_cast<QPopupMenu *>(w)->exec(p);
00252     d->currentItem = 0;
00253 }
00254 
00255 void TabWidget::slotDetachTab()
00256 {
00257     if (!d->currentItem || indexOf(d->currentItem) == -1) 
00258         d->currentItem = currentPage();
00259 
00260     if (indexOf(d->currentItem) == 0) 
00261         return;
00262 
00263     KURL url;
00264     KHTMLView* view = dynamic_cast<KHTMLView*>(d->currentItem);
00265     
00266     if (!view)
00267         return;
00268 
00269     url = view->part()->url();
00270 
00271     kapp->invokeBrowser(url.url(), "0");
00272     slotCloseTab();
00273 }
00274 
00275 void TabWidget::slotCopyLinkAddress()
00276 {
00277     if(!d->currentItem || indexOf(d->currentItem) == -1) 
00278         d->currentItem = currentPage();
00279     if(indexOf(d->currentItem) == 0) 
00280         return;
00281 
00282     KURL url;
00283     KHTMLView* view = dynamic_cast<KHTMLView*>(d->currentItem);
00284     
00285     if (!view)
00286         return;
00287 
00288     url = view->part()->url();
00289     
00290     kapp->clipboard()->setText(url.prettyURL(), QClipboard::Selection);
00291     kapp->clipboard()->setText(url.prettyURL(), QClipboard::Clipboard);
00292 }
00293 
00294 void TabWidget::slotCloseTab()
00295 {
00296     if (!d->currentItem || indexOf(d->currentItem) == -1) 
00297         d->currentItem = currentPage();
00298     if (indexOf(d->currentItem) == 0) 
00299         return;
00300     if (d->frames.find(d->currentItem) != NULL)
00301         removeFrame(d->frames.find(d->currentItem));
00302     delete d->currentItem;
00303     d->currentItem = 0;
00304 }
00305 
00306 void TabWidget::initiateDrag(int tab)
00307 {
00308     if (tab == 0) // don't initiate drag for the main tab
00309         return;
00310         
00311     Frame* frame = d->frames[page(tab)];
00312   
00313     if (frame != 0)
00314     {
00315         KURL::List lst;
00316         lst.append( frame->part()->url() );
00317         KURLDrag* drag = new KURLDrag( lst, this );
00318         drag->setPixmap( KMimeType::pixmapForURL( lst.first(), 0, KIcon::Small ) );
00319         drag->dragCopy();
00320     }
00321 }
00322 
00323 void TabWidget::slotCloseRequest(QWidget* widget)
00324 {
00325     if (d->frames.find(widget) != NULL)
00326         removeFrame(d->frames.find(widget));
00327 }
00328 } // namespace Akregator
00329 
00330 #include "tabwidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys