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 <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 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 KHTMLView* view = dynamic_cast<KHTMLView*>(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 KHTMLView* view = dynamic_cast<KHTMLView*>(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, KIcon::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"