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 TQt, and distribute the resulting executable,
00022     without including the source code for TQt in the source distribution.
00023 */
00024 
00025 #include "tabwidget.h"
00026 
00027 #include <tqstyle.h>
00028 #include <tqapplication.h>
00029 #include <tqiconset.h>
00030 #include <tqclipboard.h>
00031 #include <tqmap.h>
00032 #include <tqptrdict.h>
00033 #include <tqstring.h>
00034 #include <tqtoolbutton.h>
00035 #include <tqtooltip.h>
00036 
00037 #include <tdeapplication.h>
00038 #include <kdebug.h>
00039 #include <ktabwidget.h>
00040 #include <ktabbar.h>
00041 #include <tdepopupmenu.h>
00042 #include <krun.h>
00043 #include <tdelocale.h>
00044 #include <tdehtmlview.h>
00045 #include <tdehtml_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     TQPtrDict<Frame> frames;
00061     uint CurrentMaxLength;
00062     TQWidget* currentItem;
00063     TQToolButton* tabsClose;
00064 };
00065 
00066 TabWidget::TabWidget(TQWidget * parent, const char *name)
00067         :KTabWidget(parent, name), d(new TabWidgetPrivate)
00068 {
00069     d->CurrentMaxLength = 30;
00070     d->currentItem = 0;
00071     setMinimumSize(250,150);
00072     setTabReorderingEnabled(false);
00073     connect( this, TQT_SIGNAL( currentChanged(TQWidget *) ), this,
00074             TQT_SLOT( slotTabChanged(TQWidget *) ) );
00075     connect(this, TQT_SIGNAL(closeRequest(TQWidget*)), this, TQT_SLOT(slotCloseRequest(TQWidget*)));
00076     setHoverCloseButton(Settings::closeButtonOnTabs());
00077 
00078     d->tabsClose = new TQToolButton(this);
00079     d->tabsClose->setAccel(TQKeySequence("Ctrl+W"));
00080     connect( d->tabsClose, TQT_SIGNAL( clicked() ), this,
00081             TQT_SLOT( slotRemoveCurrentFrame() ) );
00082 
00083     d->tabsClose->setIconSet( SmallIconSet( "tab_remove" ) );
00084     d->tabsClose->adjustSize();
00085     TQToolTip::add(d->tabsClose, i18n("Close the current tab"));
00086     setCornerWidget( d->tabsClose, TopRight );
00087 }
00088 
00089 TabWidget::~TabWidget()
00090 {
00091     delete d;
00092     d = 0;
00093 }
00094 
00095 void TabWidget::slotSettingsChanged()
00096 {
00097     if (hoverCloseButton() != Settings::closeButtonOnTabs())
00098         setHoverCloseButton(Settings::closeButtonOnTabs());
00099 }
00100 
00101 void TabWidget::slotNextTab()
00102 {
00103     setCurrentPage((currentPageIndex()+1) % count());
00104 }
00105 
00106 void TabWidget::slotPreviousTab()
00107 {
00108     if (currentPageIndex() == 0)
00109         setCurrentPage(count()-1);
00110     else
00111         setCurrentPage(currentPageIndex()-1);
00112 }
00113 
00114 void TabWidget::addFrame(Frame *f)
00115 {
00116     if (!f || !f->widget()) 
00117         return;
00118     d->frames.insert(f->widget(), f);
00119     addTab(f->widget(), f->title());
00120     connect(f, TQT_SIGNAL(titleChanged(Frame*, const TQString& )), this, TQT_SLOT(slotSetTitle(Frame*, const TQString& )));
00121     slotSetTitle(f, f->title());
00122 }
00123 
00124 Frame *TabWidget::currentFrame()
00125 {
00126     TQWidget* w = currentPage();
00127     
00128     return w ? d->frames[w] : 0;
00129 }
00130 
00131 TQPtrList<Frame> TabWidget::frames() const
00132 {
00133     TQPtrList<Frame> result;
00134     TQPtrDictIterator<Frame> it(d->frames);
00135     while (it.current())
00136     {
00137         result.append(it.current());
00138         ++it;
00139     }
00140 
00141     return result;
00142 }
00143 
00144 void TabWidget::slotTabChanged(TQWidget *w)
00145 {
00146     // FIXME: Don't hardcode the tab position of main frame
00147     d->tabsClose->setDisabled(currentPageIndex() == 0);
00148     emit currentFrameChanged(d->frames[w]);
00149 }
00150 
00151 void TabWidget::slotRemoveCurrentFrame()
00152 {
00153     removeFrame(currentFrame());
00154 }
00155 
00156 void TabWidget::removeFrame(Frame *f)
00157 {
00158     f->setCompleted();
00159     d->frames.remove(f->widget());
00160     removePage(f->widget());
00161     delete f;
00162     setTitle( currentFrame()->title(), currentPage() );
00163 }
00164 
00165 // copied wholesale from KonqFrameTabs
00166 uint TabWidget::tabBarWidthForMaxChars( uint maxLength )
00167 {
00168     int hframe, overlap;
00169     hframe = tabBar()->style().pixelMetric( TQStyle::PM_TabBarTabHSpace, this );
00170     overlap = tabBar()->style().pixelMetric( TQStyle::PM_TabBarTabOverlap, this );
00171 
00172     TQFontMetrics fm = tabBar()->fontMetrics();
00173     int x = 0;
00174     for( int i=0; i < count(); ++i ) {
00175         Frame *f=d->frames[page(i)];
00176         TQString newTitle=f->title();
00177         if ( newTitle.length() > maxLength )
00178             newTitle = newTitle.left( maxLength-3 ) + "...";
00179 
00180         TQTab* tab = tabBar()->tabAt( i );
00181         int lw = fm.width( newTitle );
00182         int iw = 0;
00183         if ( tab->iconSet() )
00184             iw = tab->iconSet()->pixmap( TQIconSet::Small, TQIconSet::Normal ).width() + 4;
00185 
00186         x += ( tabBar()->style().tqsizeFromContents( TQStyle::CT_TabBarTab, this,                             TQSize( TQMAX( lw + hframe + iw, TQApplication::globalStrut().width() ), 0 ), TQStyleOption( tab ) ) ).width();
00187     }
00188     return x;
00189 }
00190 
00191 void TabWidget::slotSetTitle(Frame* frame, const TQString& title)
00192 {
00193     setTitle(title, frame->widget());
00194 }
00195 
00196 void TabWidget::setTitle( const TQString &title , TQWidget* sender)
00197 {
00198     removeTabToolTip( sender );
00199    
00200     uint lcw=0, rcw=0;
00201     int tabBarHeight = tabBar()->sizeHint().height();
00202     if ( cornerWidget( TopLeft ) && cornerWidget( TopLeft )->isVisible() )
00203         lcw = TQMAX( cornerWidget( TopLeft )->width(), tabBarHeight );
00204     if ( cornerWidget( TopRight ) && cornerWidget( TopRight )->isVisible() )
00205         rcw = TQMAX( cornerWidget( TopRight )->width(), tabBarHeight );
00206     uint maxTabBarWidth = width() - lcw - rcw;
00207 
00208     uint newMaxLength=30;
00209     for ( ; newMaxLength > 3; newMaxLength-- ) 
00210 {
00211         if ( tabBarWidthForMaxChars( newMaxLength ) < maxTabBarWidth )
00212             break;
00213     }
00214     TQString newTitle = title;
00215     if ( newTitle.length() > newMaxLength )
00216     {
00217         setTabToolTip( sender, newTitle );
00218         newTitle = newTitle.left( newMaxLength-3 ) + "...";
00219     }
00220 
00221     newTitle.replace( '&', "&&" );
00222     if ( tabLabel( sender ) != newTitle )
00223         changeTab( sender, newTitle );
00224 
00225     if( newMaxLength != d->CurrentMaxLength )
00226     {
00227         for( int i = 0; i < count(); ++i)
00228         {
00229             Frame *f=d->frames[page(i)];
00230             newTitle=f->title();
00231             removeTabToolTip( page( i ) );
00232             if ( newTitle.length() > newMaxLength )
00233             {
00234                 setTabToolTip( page( i ), newTitle );
00235                 newTitle = newTitle.left( newMaxLength-3 ) + "...";
00236             }
00237 
00238             newTitle.replace( '&', "&&" );
00239             if ( newTitle != tabLabel( page( i ) ) )
00240                     changeTab( page( i ), newTitle );
00241         }
00242         d->CurrentMaxLength = newMaxLength;
00243     }
00244 }
00245 
00246 void TabWidget::contextMenu(int i, const TQPoint &p)
00247 {
00248     TQWidget* w = ActionManager::getInstance()->container("tab_popup");
00249     d->currentItem = page(i);
00250     //kdDebug() << indexOf(d->currentItem) << endl;
00251     if (w && indexOf(d->currentItem) != 0)
00252         static_cast<TQPopupMenu *>(w)->exec(p);
00253     d->currentItem = 0;
00254 }
00255 
00256 void TabWidget::slotDetachTab()
00257 {
00258     if (!d->currentItem || indexOf(d->currentItem) == -1) 
00259         d->currentItem = currentPage();
00260 
00261     if (indexOf(d->currentItem) == 0) 
00262         return;
00263 
00264     KURL url;
00265     TDEHTMLView* view = dynamic_cast<TDEHTMLView*>(d->currentItem);
00266     
00267     if (!view)
00268         return;
00269 
00270     url = view->part()->url();
00271 
00272     kapp->invokeBrowser(url.url(), "0");
00273     slotCloseTab();
00274 }
00275 
00276 void TabWidget::slotCopyLinkAddress()
00277 {
00278     if(!d->currentItem || indexOf(d->currentItem) == -1) 
00279         d->currentItem = currentPage();
00280     if(indexOf(d->currentItem) == 0) 
00281         return;
00282 
00283     KURL url;
00284     TDEHTMLView* view = dynamic_cast<TDEHTMLView*>(d->currentItem);
00285     
00286     if (!view)
00287         return;
00288 
00289     url = view->part()->url();
00290     
00291     kapp->clipboard()->setText(url.prettyURL(), TQClipboard::Selection);
00292     kapp->clipboard()->setText(url.prettyURL(), TQClipboard::Clipboard);
00293 }
00294 
00295 void TabWidget::slotCloseTab()
00296 {
00297     if (!d->currentItem || indexOf(d->currentItem) == -1) 
00298         d->currentItem = currentPage();
00299     if (indexOf(d->currentItem) == 0) 
00300         return;
00301     if (d->frames.find(d->currentItem) != NULL)
00302         removeFrame(d->frames.find(d->currentItem));
00303     delete d->currentItem;
00304     d->currentItem = 0;
00305 }
00306 
00307 void TabWidget::initiateDrag(int tab)
00308 {
00309     if (tab == 0) // don't initiate drag for the main tab
00310         return;
00311         
00312     Frame* frame = d->frames[page(tab)];
00313   
00314     if (frame != 0)
00315     {
00316         KURL::List lst;
00317         lst.append( frame->part()->url() );
00318         KURLDrag* drag = new KURLDrag( lst, this );
00319         drag->setPixmap( KMimeType::pixmapForURL( lst.first(), 0, TDEIcon::Small ) );
00320         drag->dragCopy();
00321     }
00322 }
00323 
00324 void TabWidget::slotCloseRequest(TQWidget* widget)
00325 {
00326     if (d->frames.find(widget) != NULL)
00327         removeFrame(d->frames.find(widget));
00328 }
00329 } // namespace Akregator
00330 
00331 #include "tabwidget.moc"