akregator/src

tabwidget.cpp
1 /*
2  This file is part of Akregator.
3 
4  Copyright (C) 2004 Sashmit Bhaduri <smt@vfemail.net>
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20  As a special exception, permission is given to link this program
21  with any edition of TQt, and distribute the resulting executable,
22  without including the source code for TQt in the source distribution.
23 */
24 
25 #include "tabwidget.h"
26 
27 #include <tqstyle.h>
28 #include <tqapplication.h>
29 #include <tqiconset.h>
30 #include <tqclipboard.h>
31 #include <tqmap.h>
32 #include <tqptrdict.h>
33 #include <tqstring.h>
34 #include <tqtoolbutton.h>
35 #include <tqtooltip.h>
36 
37 #include <tdeapplication.h>
38 #include <kdebug.h>
39 #include <ktabwidget.h>
40 #include <ktabbar.h>
41 #include <tdepopupmenu.h>
42 #include <krun.h>
43 #include <tdelocale.h>
44 #include <tdehtmlview.h>
45 #include <tdehtml_part.h>
46 #include <kiconloader.h>
47 #include <kurl.h>
48 #include <kurldrag.h>
49 #include <kmimetype.h>
50 
51 #include "actionmanager.h"
52 #include "frame.h"
53 #include "akregatorconfig.h"
54 
55 namespace Akregator {
56 
57 class TabWidget::TabWidgetPrivate
58 {
59  public:
60  TQPtrDict<Frame> frames;
61  uint CurrentMaxLength;
62  TQWidget* currentItem;
63  TQToolButton* tabsClose;
64 };
65 
66 TabWidget::TabWidget(TQWidget * parent, const char *name)
67  :KTabWidget(parent, name), d(new TabWidgetPrivate)
68 {
69  d->CurrentMaxLength = 30;
70  d->currentItem = 0;
71  setMinimumSize(250,150);
72  setTabReorderingEnabled(false);
73  connect( this, TQ_SIGNAL( currentChanged(TQWidget *) ), this,
74  TQ_SLOT( slotTabChanged(TQWidget *) ) );
75  connect(this, TQ_SIGNAL(closeRequest(TQWidget*)), this, TQ_SLOT(slotCloseRequest(TQWidget*)));
76  setHoverCloseButton(Settings::closeButtonOnTabs());
77 
78  d->tabsClose = new TQToolButton(this);
79  d->tabsClose->setAccel(TQKeySequence("Ctrl+W"));
80  connect( d->tabsClose, TQ_SIGNAL( clicked() ), this,
81  TQ_SLOT( slotRemoveCurrentFrame() ) );
82 
83  d->tabsClose->setIconSet( SmallIconSet( "tab_remove" ) );
84  d->tabsClose->adjustSize();
85  TQToolTip::add(d->tabsClose, i18n("Close the current tab"));
86  setCornerWidget( d->tabsClose, TopRight );
87 }
88 
89 TabWidget::~TabWidget()
90 {
91  delete d;
92  d = 0;
93 }
94 
95 void TabWidget::slotSettingsChanged()
96 {
97  if (hoverCloseButton() != Settings::closeButtonOnTabs())
98  setHoverCloseButton(Settings::closeButtonOnTabs());
99 }
100 
101 void TabWidget::slotNextTab()
102 {
103  setCurrentPage((currentPageIndex()+1) % count());
104 }
105 
106 void TabWidget::slotPreviousTab()
107 {
108  if (currentPageIndex() == 0)
109  setCurrentPage(count()-1);
110  else
111  setCurrentPage(currentPageIndex()-1);
112 }
113 
114 void TabWidget::addFrame(Frame *f)
115 {
116  if (!f || !f->widget())
117  return;
118  d->frames.insert(f->widget(), f);
119  addTab(f->widget(), f->title());
120  connect(f, TQ_SIGNAL(titleChanged(Frame*, const TQString& )), this, TQ_SLOT(slotSetTitle(Frame*, const TQString& )));
121  slotSetTitle(f, f->title());
122 }
123 
124 Frame *TabWidget::currentFrame()
125 {
126  TQWidget* w = currentPage();
127 
128  return w ? d->frames[w] : 0;
129 }
130 
131 TQPtrList<Frame> TabWidget::frames() const
132 {
133  TQPtrList<Frame> result;
134  TQPtrDictIterator<Frame> it(d->frames);
135  while (it.current())
136  {
137  result.append(it.current());
138  ++it;
139  }
140 
141  return result;
142 }
143 
144 void TabWidget::slotTabChanged(TQWidget *w)
145 {
146  // FIXME: Don't hardcode the tab position of main frame
147  d->tabsClose->setDisabled(currentPageIndex() == 0);
148  emit currentFrameChanged(d->frames[w]);
149 }
150 
151 void TabWidget::slotRemoveCurrentFrame()
152 {
153  removeFrame(currentFrame());
154 }
155 
156 void TabWidget::removeFrame(Frame *f)
157 {
158  f->setCompleted();
159  d->frames.remove(f->widget());
160  removePage(f->widget());
161  delete f;
162  setTitle( currentFrame()->title(), currentPage() );
163 }
164 
165 // copied wholesale from KonqFrameTabs
166 uint TabWidget::tabBarWidthForMaxChars( uint maxLength )
167 {
168  int hframe, overlap;
169  hframe = tabBar()->style().pixelMetric( TQStyle::PM_TabBarTabHSpace, this );
170  overlap = tabBar()->style().pixelMetric( TQStyle::PM_TabBarTabOverlap, this );
171 
172  TQFontMetrics fm = tabBar()->fontMetrics();
173  int x = 0;
174  for( int i=0; i < count(); ++i ) {
175  Frame *f=d->frames[page(i)];
176  TQString newTitle=f->title();
177  if ( newTitle.length() > maxLength )
178  newTitle = newTitle.left( maxLength-3 ) + "...";
179 
180  TQTab* tab = tabBar()->tabAt( i );
181  int lw = fm.width( newTitle );
182  int iw = 0;
183  if ( tab->iconSet() )
184  iw = tab->iconSet()->pixmap( TQIconSet::Small, TQIconSet::Normal ).width() + 4;
185 
186  x += ( tabBar()->style().sizeFromContents( TQStyle::CT_TabBarTab, this, TQSize( TQMAX( lw + hframe + iw, TQApplication::globalStrut().width() ), 0 ), TQStyleOption( tab ) ) ).width();
187  }
188  return x;
189 }
190 
191 void TabWidget::slotSetTitle(Frame* frame, const TQString& title)
192 {
193  setTitle(title, frame->widget());
194 }
195 
196 void TabWidget::setTitle( const TQString &title , TQWidget* sender)
197 {
198  removeTabToolTip( sender );
199 
200  uint lcw=0, rcw=0;
201  int tabBarHeight = tabBar()->sizeHint().height();
202  if ( cornerWidget( TopLeft ) && cornerWidget( TopLeft )->isVisible() )
203  lcw = TQMAX( cornerWidget( TopLeft )->width(), tabBarHeight );
204  if ( cornerWidget( TopRight ) && cornerWidget( TopRight )->isVisible() )
205  rcw = TQMAX( cornerWidget( TopRight )->width(), tabBarHeight );
206  uint maxTabBarWidth = width() - lcw - rcw;
207 
208  uint newMaxLength=30;
209  for ( ; newMaxLength > 3; newMaxLength-- )
210 {
211  if ( tabBarWidthForMaxChars( newMaxLength ) < maxTabBarWidth )
212  break;
213  }
214  TQString newTitle = title;
215  if ( newTitle.length() > newMaxLength )
216  {
217  setTabToolTip( sender, newTitle );
218  newTitle = newTitle.left( newMaxLength-3 ) + "...";
219  }
220 
221  newTitle.replace( '&', "&&" );
222  if ( tabLabel( sender ) != newTitle )
223  changeTab( sender, newTitle );
224 
225  if( newMaxLength != d->CurrentMaxLength )
226  {
227  for( int i = 0; i < count(); ++i)
228  {
229  Frame *f=d->frames[page(i)];
230  newTitle=f->title();
231  removeTabToolTip( page( i ) );
232  if ( newTitle.length() > newMaxLength )
233  {
234  setTabToolTip( page( i ), newTitle );
235  newTitle = newTitle.left( newMaxLength-3 ) + "...";
236  }
237 
238  newTitle.replace( '&', "&&" );
239  if ( newTitle != tabLabel( page( i ) ) )
240  changeTab( page( i ), newTitle );
241  }
242  d->CurrentMaxLength = newMaxLength;
243  }
244 }
245 
246 void TabWidget::contextMenu(int i, const TQPoint &p)
247 {
248  TQWidget* w = ActionManager::getInstance()->container("tab_popup");
249  d->currentItem = page(i);
250  //kdDebug() << indexOf(d->currentItem) << endl;
251  if (w && indexOf(d->currentItem) != 0)
252  static_cast<TQPopupMenu *>(w)->exec(p);
253  d->currentItem = 0;
254 }
255 
256 void TabWidget::slotDetachTab()
257 {
258  if (!d->currentItem || indexOf(d->currentItem) == -1)
259  d->currentItem = currentPage();
260 
261  if (indexOf(d->currentItem) == 0)
262  return;
263 
264  KURL url;
265  TDEHTMLView* view = dynamic_cast<TDEHTMLView*>(d->currentItem);
266 
267  if (!view)
268  return;
269 
270  url = view->part()->url();
271 
272  kapp->invokeBrowser(url.url(), "0");
273  slotCloseTab();
274 }
275 
276 void TabWidget::slotCopyLinkAddress()
277 {
278  if(!d->currentItem || indexOf(d->currentItem) == -1)
279  d->currentItem = currentPage();
280  if(indexOf(d->currentItem) == 0)
281  return;
282 
283  KURL url;
284  TDEHTMLView* view = dynamic_cast<TDEHTMLView*>(d->currentItem);
285 
286  if (!view)
287  return;
288 
289  url = view->part()->url();
290 
291  kapp->clipboard()->setText(url.prettyURL(), TQClipboard::Selection);
292  kapp->clipboard()->setText(url.prettyURL(), TQClipboard::Clipboard);
293 }
294 
295 void TabWidget::slotCloseTab()
296 {
297  if (!d->currentItem || indexOf(d->currentItem) == -1)
298  d->currentItem = currentPage();
299  if (indexOf(d->currentItem) == 0)
300  return;
301  if (d->frames.find(d->currentItem) != NULL)
302  removeFrame(d->frames.find(d->currentItem));
303  delete d->currentItem;
304  d->currentItem = 0;
305 }
306 
307 void TabWidget::initiateDrag(int tab)
308 {
309  if (tab == 0) // don't initiate drag for the main tab
310  return;
311 
312  Frame* frame = d->frames[page(tab)];
313 
314  if (frame != 0)
315  {
316  KURL::List lst;
317  lst.append( frame->part()->url() );
318  KURLDrag* drag = new KURLDrag( lst, this );
319  drag->setPixmap( KMimeType::pixmapForURL( lst.first(), 0, TDEIcon::Small ) );
320  drag->dragCopy();
321  }
322 }
323 
324 void TabWidget::slotCloseRequest(TQWidget* widget)
325 {
326  if (d->frames.find(widget) != NULL)
327  removeFrame(d->frames.find(widget));
328 }
329 } // namespace Akregator
330 
331 #include "tabwidget.moc"