tdebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

konq_actions.cc 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. /* This file is part of the KDE project
  2. Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public License
  12. along with this library; see the file COPYING.LIB. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  14. Boston, MA 02110-1301, USA.
  15. */
  16. #include "konq_actions.h"
  17. #include <assert.h>
  18. #include <tdetoolbarbutton.h>
  19. #include <kanimwidget.h>
  20. #include <kdebug.h>
  21. #include <kstringhandler.h>
  22. #include <konq_pixmapprovider.h>
  23. #include <kiconloader.h>
  24. #include <tdepopupmenu.h>
  25. #include <tdeapplication.h>
  26. #include "konq_view.h"
  27. #include "konq_settingsxt.h"
  28. template class TQPtrList<KonqHistoryEntry>;
  29. /////////////////
  30. //static - used by KonqHistoryAction and KonqBidiHistoryAction
  31. void KonqBidiHistoryAction::fillHistoryPopup( const TQPtrList<HistoryEntry> &history,
  32. TQPopupMenu * popup,
  33. bool onlyBack,
  34. bool onlyForward,
  35. bool checkCurrentItem,
  36. uint startPos )
  37. {
  38. assert ( popup ); // kill me if this 0... :/
  39. //kdDebug(1202) << "fillHistoryPopup position: " << history.at() << endl;
  40. HistoryEntry * current = history.current();
  41. TQPtrListIterator<HistoryEntry> it( history );
  42. if (onlyBack || onlyForward)
  43. {
  44. it += history.at(); // Jump to current item
  45. if ( !onlyForward ) --it; else ++it; // And move off it
  46. } else if ( startPos )
  47. it += startPos; // Jump to specified start pos
  48. uint i = 0;
  49. while ( it.current() )
  50. {
  51. TQString text = it.current()->title;
  52. text = KStringHandler::cEmSqueeze(text, popup->fontMetrics(), 30); //CT: squeeze
  53. text.replace( "&", "&&" );
  54. if ( checkCurrentItem && it.current() == current )
  55. {
  56. int id = popup->insertItem( text ); // no pixmap if checked
  57. popup->setItemChecked( id, true );
  58. } else
  59. popup->insertItem( KonqPixmapProvider::self()->pixmapFor(
  60. it.current()->url.url() ), text );
  61. if ( ++i > 10 )
  62. break;
  63. if ( !onlyForward ) --it; else ++it;
  64. }
  65. //kdDebug(1202) << "After fillHistoryPopup position: " << history.at() << endl;
  66. }
  67. ///////////////////////////////
  68. KonqBidiHistoryAction::KonqBidiHistoryAction ( const TQString & text, TQObject* parent, const char* name )
  69. : TDEAction( text, 0, parent, name )
  70. {
  71. setShortcutConfigurable(false);
  72. m_firstIndex = 0;
  73. m_goMenu = 0L;
  74. }
  75. int KonqBidiHistoryAction::plug( TQWidget *widget, int index )
  76. {
  77. if (kapp && !kapp->authorizeTDEAction(name()))
  78. return -1;
  79. // Go menu
  80. if ( widget->inherits(TQPOPUPMENU_OBJECT_NAME_STRING) )
  81. {
  82. m_goMenu = (TQPopupMenu*)widget;
  83. // Forward signal (to main view)
  84. connect( m_goMenu, TQT_SIGNAL( aboutToShow() ),
  85. this, TQT_SIGNAL( menuAboutToShow() ) );
  86. connect( m_goMenu, TQT_SIGNAL( activated( int ) ),
  87. this, TQT_SLOT( slotActivated( int ) ) );
  88. //kdDebug(1202) << "m_goMenu->count()=" << m_goMenu->count() << endl;
  89. // Store how many items the menu already contains.
  90. // This means, the KonqBidiHistoryAction has to be plugged LAST in a menu !
  91. m_firstIndex = m_goMenu->count();
  92. return m_goMenu->count(); // hmmm, what should this be ?
  93. }
  94. return TDEAction::plug( widget, index );
  95. }
  96. void KonqBidiHistoryAction::fillGoMenu( const TQPtrList<HistoryEntry> & history )
  97. {
  98. if (history.isEmpty())
  99. return; // nothing to do
  100. //kdDebug(1202) << "fillGoMenu position: " << history.at() << endl;
  101. if ( m_firstIndex == 0 ) // should never happen since done in plug
  102. m_firstIndex = m_goMenu->count();
  103. else
  104. { // Clean up old history (from the end, to avoid shifts)
  105. for ( uint i = m_goMenu->count()-1 ; i >= m_firstIndex; i-- )
  106. m_goMenu->removeItemAt( i );
  107. }
  108. // TODO perhaps smarter algorithm (rename existing items, create new ones only if not enough) ?
  109. // Ok, we want to show 10 items in all, among which the current url...
  110. if ( history.count() <= 9 )
  111. {
  112. // First case: limited history in both directions -> show it all
  113. m_startPos = history.count() - 1; // Start right from the end
  114. } else
  115. // Second case: big history, in one or both directions
  116. {
  117. // Assume both directions first (in this case we place the current URL in the middle)
  118. m_startPos = history.at() + 4;
  119. // Forward not big enough ?
  120. if ( history.at() > (int)history.count() - 4 )
  121. m_startPos = history.count() - 1;
  122. }
  123. Q_ASSERT( m_startPos >= 0 && (uint)m_startPos < history.count() );
  124. if ( m_startPos < 0 || (uint)m_startPos >= history.count() )
  125. {
  126. kdWarning() << "m_startPos=" << m_startPos << " history.count()=" << history.count() << endl;
  127. return;
  128. }
  129. m_currentPos = history.at(); // for slotActivated
  130. KonqBidiHistoryAction::fillHistoryPopup( history, m_goMenu, false, false, true, m_startPos );
  131. }
  132. void KonqBidiHistoryAction::slotActivated( int id )
  133. {
  134. // 1 for first item in the list, etc.
  135. int index = m_goMenu->indexOf(id) - m_firstIndex + 1;
  136. if ( index > 0 )
  137. {
  138. kdDebug(1202) << "Item clicked has index " << index << endl;
  139. // -1 for one step back, 0 for don't move, +1 for one step forward, etc.
  140. int steps = ( m_startPos+1 ) - index - m_currentPos; // make a drawing to understand this :-)
  141. kdDebug(1202) << "Emit activated with steps = " << steps << endl;
  142. emit activated( steps );
  143. }
  144. }
  145. ///////////////////////////////
  146. KonqLogoAction::KonqLogoAction( const TQString& text, int accel, TQObject* parent, const char* name )
  147. : TDEAction( text, accel, parent, name )
  148. {
  149. }
  150. KonqLogoAction::KonqLogoAction( const TQString& text, int accel,
  151. TQObject* receiver, const char* slot, TQObject* parent, const char* name )
  152. : TDEAction( text, accel, receiver, slot, parent, name )
  153. {
  154. }
  155. KonqLogoAction::KonqLogoAction( const TQString& text, const TQIconSet& pix, int accel, TQObject* parent, const char* name )
  156. : TDEAction( text, pix, accel, parent, name )
  157. {
  158. }
  159. KonqLogoAction::KonqLogoAction( const TQString& text, const TQIconSet& pix,int accel, TQObject* receiver, const char* slot, TQObject* parent, const char* name )
  160. : TDEAction( text, pix, accel, receiver, slot, parent, name )
  161. {
  162. }
  163. KonqLogoAction::KonqLogoAction( const TQStringList& icons, TQObject* receiver,
  164. const char* slot, TQObject* parent,
  165. const char* name )
  166. : TDEAction( 0L, 0, receiver, slot, parent, name ) // text missing !
  167. {
  168. iconList = icons;
  169. }
  170. void KonqLogoAction::start()
  171. {
  172. int len = containerCount();
  173. for ( int i = 0; i < len; i++ )
  174. {
  175. TQWidget *w = container( i );
  176. if ( w->inherits( "TDEToolBar" ) )
  177. {
  178. KAnimWidget *anim = ((TDEToolBar *)w)->animatedWidget( menuId( i ) );
  179. anim->start();
  180. }
  181. }
  182. }
  183. void KonqLogoAction::stop()
  184. {
  185. int len = containerCount();
  186. for ( int i = 0; i < len; i++ )
  187. {
  188. TQWidget *w = container( i );
  189. if ( w->inherits( "TDEToolBar" ) )
  190. {
  191. KAnimWidget *anim = ((TDEToolBar *)w)->animatedWidget( menuId( i ) );
  192. anim->stop();
  193. }
  194. }
  195. }
  196. void KonqLogoAction::updateIcon(int id)
  197. {
  198. TQWidget *w = container( id );
  199. if ( w->inherits( "TDEToolBar" ) )
  200. {
  201. KAnimWidget *anim = ((TDEToolBar *)w)->animatedWidget( menuId( id ) );
  202. anim->setIcons(icon());
  203. }
  204. }
  205. int KonqLogoAction::plug( TQWidget *widget, int index )
  206. {
  207. if (kapp && !kapp->authorizeTDEAction(name()))
  208. return -1;
  209. /*
  210. if ( widget->inherits( "TDEMainWindow" ) )
  211. {
  212. ((TDEMainWindow*)widget)->setIndicatorWidget(m_logoLabel);
  213. addContainer( widget, -1 );
  214. return containerCount() - 1;
  215. }
  216. */
  217. if ( widget->inherits( "TDEToolBar" ) )
  218. {
  219. TDEToolBar *bar = (TDEToolBar *)widget;
  220. int id_ = getToolButtonID();
  221. bar->insertAnimatedWidget( id_, this, TQT_SIGNAL(activated()), TQString("trinity"), index );
  222. bar->alignItemRight( id_ );
  223. addContainer( bar, id_ );
  224. connect( bar, TQT_SIGNAL( destroyed() ), this, TQT_SLOT( slotDestroyed() ) );
  225. return containerCount() - 1;
  226. }
  227. int containerId = TDEAction::plug( widget, index );
  228. return containerId;
  229. }
  230. ///////////
  231. KonqViewModeAction::KonqViewModeAction( const TQString &text, const TQString &icon,
  232. TQObject *parent, const char *name )
  233. : TDERadioAction( text, icon, 0, parent, name )
  234. {
  235. m_menu = new TQPopupMenu;
  236. connect( m_menu, TQT_SIGNAL( aboutToShow() ),
  237. this, TQT_SLOT( slotPopupAboutToShow() ) );
  238. connect( m_menu, TQT_SIGNAL( activated( int ) ),
  239. this, TQT_SLOT( slotPopupActivated() ) );
  240. connect( m_menu, TQT_SIGNAL( aboutToHide() ),
  241. this, TQT_SLOT( slotPopupAboutToHide() ) );
  242. }
  243. KonqViewModeAction::~KonqViewModeAction()
  244. {
  245. delete m_menu;
  246. }
  247. int KonqViewModeAction::plug( TQWidget *widget, int index )
  248. {
  249. int res = TDERadioAction::plug( widget, index );
  250. if ( widget->inherits( "TDEToolBar" ) && (res != -1) )
  251. {
  252. TDEToolBar *toolBar = static_cast<TDEToolBar *>( widget );
  253. TDEToolBarButton *button = toolBar->getButton( itemId( res ) );
  254. if ( m_menu->count() > 1 )
  255. button->setDelayedPopup( m_menu, false );
  256. }
  257. return res;
  258. }
  259. void KonqViewModeAction::slotPopupAboutToShow()
  260. {
  261. m_popupActivated = false;
  262. }
  263. void KonqViewModeAction::slotPopupActivated()
  264. {
  265. m_popupActivated = true;
  266. }
  267. void KonqViewModeAction::slotPopupAboutToHide()
  268. {
  269. if ( !m_popupActivated )
  270. {
  271. int i = 0;
  272. for (; i < containerCount(); ++i )
  273. {
  274. TQWidget *widget = container( i );
  275. if ( !widget->inherits( "TDEToolBar" ) )
  276. continue;
  277. TDEToolBar *tb = static_cast<TDEToolBar *>( widget );
  278. TDEToolBarButton *button = tb->getButton( itemId( i ) );
  279. button->setDown( isChecked() );
  280. }
  281. }
  282. }
  283. MostOftenList * KonqMostOftenURLSAction::s_mostEntries = 0L;
  284. uint KonqMostOftenURLSAction::s_maxEntries = 0;
  285. KonqMostOftenURLSAction::KonqMostOftenURLSAction( const TQString& text,
  286. TQObject *parent,
  287. const char *name )
  288. : TDEActionMenu( text, "goto", parent, name )
  289. {
  290. setDelayed( false );
  291. connect( popupMenu(), TQT_SIGNAL( aboutToShow() ), TQT_SLOT( slotFillMenu() ));
  292. //connect( popupMenu(), TQT_SIGNAL( aboutToHide() ), TQT_SLOT( slotClearMenu() ));
  293. connect( popupMenu(), TQT_SIGNAL( activated( int ) ),
  294. TQT_SLOT( slotActivated(int) ));
  295. // Need to do all this upfront for a correct initial state
  296. init();
  297. }
  298. KonqMostOftenURLSAction::~KonqMostOftenURLSAction()
  299. {
  300. }
  301. void KonqMostOftenURLSAction::init()
  302. {
  303. s_maxEntries = KonqSettings::numberofmostvisitedURLs();
  304. KonqHistoryManager *mgr = KonqHistoryManager::kself();
  305. setEnabled( !mgr->entries().isEmpty() && s_maxEntries > 0 );
  306. }
  307. void KonqMostOftenURLSAction::parseHistory() // only ever called once
  308. {
  309. KonqHistoryManager *mgr = KonqHistoryManager::kself();
  310. KonqHistoryIterator it( mgr->entries() );
  311. connect( mgr, TQT_SIGNAL( entryAdded( const KonqHistoryEntry * )),
  312. TQT_SLOT( slotEntryAdded( const KonqHistoryEntry * )));
  313. connect( mgr, TQT_SIGNAL( entryRemoved( const KonqHistoryEntry * )),
  314. TQT_SLOT( slotEntryRemoved( const KonqHistoryEntry * )));
  315. connect( mgr, TQT_SIGNAL( cleared() ), TQT_SLOT( slotHistoryCleared() ));
  316. s_mostEntries = new MostOftenList; // exit() will clean this up for now
  317. for ( uint i = 0; it.current() && i < s_maxEntries; i++ ) {
  318. s_mostEntries->append( it.current() );
  319. ++it;
  320. }
  321. s_mostEntries->sort();
  322. while ( it.current() ) {
  323. KonqHistoryEntry *leastOften = s_mostEntries->first();
  324. KonqHistoryEntry *entry = it.current();
  325. if ( leastOften->numberOfTimesVisited < entry->numberOfTimesVisited ) {
  326. s_mostEntries->removeFirst();
  327. s_mostEntries->inSort( entry );
  328. }
  329. ++it;
  330. }
  331. }
  332. void KonqMostOftenURLSAction::slotEntryAdded( const KonqHistoryEntry *entry )
  333. {
  334. // if it's already present, remove it, and inSort it
  335. s_mostEntries->removeRef( entry );
  336. if ( s_mostEntries->count() >= s_maxEntries ) {
  337. KonqHistoryEntry *leastOften = s_mostEntries->first();
  338. if ( leastOften->numberOfTimesVisited < entry->numberOfTimesVisited ) {
  339. s_mostEntries->removeFirst();
  340. s_mostEntries->inSort( entry );
  341. }
  342. }
  343. else
  344. s_mostEntries->inSort( entry );
  345. setEnabled( !s_mostEntries->isEmpty() );
  346. }
  347. void KonqMostOftenURLSAction::slotEntryRemoved( const KonqHistoryEntry *entry )
  348. {
  349. s_mostEntries->removeRef( entry );
  350. setEnabled( !s_mostEntries->isEmpty() );
  351. }
  352. void KonqMostOftenURLSAction::slotHistoryCleared()
  353. {
  354. s_mostEntries->clear();
  355. setEnabled( false );
  356. }
  357. void KonqMostOftenURLSAction::slotFillMenu()
  358. {
  359. if ( !s_mostEntries ) // first time
  360. parseHistory();
  361. popupMenu()->clear();
  362. m_popupList.clear();
  363. int id = s_mostEntries->count() -1;
  364. KonqHistoryEntry *entry = s_mostEntries->at( id );
  365. while ( entry ) {
  366. // we take either title, typedURL or URL (in this order)
  367. TQString text = entry->title.isEmpty() ? (entry->typedURL.isEmpty() ?
  368. entry->url.prettyURL() :
  369. entry->typedURL) :
  370. entry->title;
  371. popupMenu()->insertItem(
  372. KonqPixmapProvider::self()->pixmapFor( entry->url.url() ),
  373. text, id );
  374. // Keep a copy of the URLs being shown in the menu
  375. // This prevents crashes when another process tells us to remove an entry.
  376. m_popupList.prepend( entry->url );
  377. entry = (id > 0) ? s_mostEntries->at( --id ) : 0L;
  378. }
  379. setEnabled( !s_mostEntries->isEmpty() );
  380. Q_ASSERT( s_mostEntries->count() == m_popupList.count() );
  381. }
  382. #if 0
  383. void KonqMostOftenURLSAction::slotClearMenu()
  384. {
  385. // Warning this is called _before_ slotActivated, when activating a menu item.
  386. // So e.g. don't clear m_popupList here.
  387. }
  388. #endif
  389. void KonqMostOftenURLSAction::slotActivated( int id )
  390. {
  391. Q_ASSERT( !m_popupList.isEmpty() ); // can not happen
  392. Q_ASSERT( id < (int)m_popupList.count() );
  393. KURL url = m_popupList[ id ];
  394. if ( url.isValid() )
  395. emit activated( url );
  396. else
  397. kdWarning() << "Invalid url: " << url.prettyURL() << endl;
  398. m_popupList.clear();
  399. }
  400. // sort by numberOfTimesVisited (least often goes first)
  401. int MostOftenList::compareItems( TQPtrCollection::Item item1,
  402. TQPtrCollection::Item item2)
  403. {
  404. KonqHistoryEntry *entry1 = static_cast<KonqHistoryEntry *>( item1 );
  405. KonqHistoryEntry *entry2 = static_cast<KonqHistoryEntry *>( item2 );
  406. if ( entry1->numberOfTimesVisited > entry2->numberOfTimesVisited )
  407. return 1;
  408. else if ( entry1->numberOfTimesVisited < entry2->numberOfTimesVisited )
  409. return -1;
  410. else
  411. return 0;
  412. }
  413. #include "konq_actions.moc"