TDE core libraries
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.

kateviewhelpers.cpp 31KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. /* This file is part of the KDE libraries
  2. Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
  3. Copyright (C) 2001 Anders Lund <anders@alweb.dk>
  4. Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License version 2 as published by the Free Software Foundation.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. #include "kateviewhelpers.h"
  18. #include "kateviewhelpers.moc"
  19. #include "../interfaces/document.h"
  20. #include "../interfaces/katecmd.h"
  21. #include "kateattribute.h"
  22. #include "katecodefoldinghelpers.h"
  23. #include "kateconfig.h"
  24. #include "katedocument.h"
  25. #include "katefactory.h"
  26. #include "katerenderer.h"
  27. #include "kateview.h"
  28. #include "kateviewinternal.h"
  29. #include <tdeapplication.h>
  30. #include <tdeglobalsettings.h>
  31. #include <tdelocale.h>
  32. #include <knotifyclient.h>
  33. #include <tdeglobal.h>
  34. #include <kcharsets.h>
  35. #include <tdepopupmenu.h>
  36. #include <tqcursor.h>
  37. #include <tqpainter.h>
  38. #include <tqpopupmenu.h>
  39. #include <tqstyle.h>
  40. #include <tqtimer.h>
  41. #include <tqwhatsthis.h>
  42. #include <tqregexp.h>
  43. #include <tqtextcodec.h>
  44. #include <math.h>
  45. #include <kdebug.h>
  46. //BEGIN KateScrollBar
  47. KateScrollBar::KateScrollBar (Orientation orientation, KateViewInternal* parent, const char* name)
  48. : TQScrollBar (orientation, parent->m_view, name)
  49. , m_middleMouseDown (false)
  50. , m_view(parent->m_view)
  51. , m_doc(parent->m_doc)
  52. , m_viewInternal(parent)
  53. , m_topMargin(-1)
  54. , m_bottomMargin(-1)
  55. , m_savVisibleLines(0)
  56. , m_showMarks(false)
  57. {
  58. connect(this, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(sliderMaybeMoved(int)));
  59. connect(m_doc, TQT_SIGNAL(marksChanged()), this, TQT_SLOT(marksChanged()));
  60. m_lines.setAutoDelete(true);
  61. }
  62. void KateScrollBar::mousePressEvent(TQMouseEvent* e)
  63. {
  64. if (e->button() == Qt::MidButton)
  65. m_middleMouseDown = true;
  66. TQScrollBar::mousePressEvent(e);
  67. redrawMarks();
  68. }
  69. void KateScrollBar::mouseReleaseEvent(TQMouseEvent* e)
  70. {
  71. TQScrollBar::mouseReleaseEvent(e);
  72. m_middleMouseDown = false;
  73. redrawMarks();
  74. }
  75. void KateScrollBar::mouseMoveEvent(TQMouseEvent* e)
  76. {
  77. TQScrollBar::mouseMoveEvent(e);
  78. if (e->state() | Qt::LeftButton)
  79. redrawMarks();
  80. }
  81. void KateScrollBar::paintEvent(TQPaintEvent *e)
  82. {
  83. TQScrollBar::paintEvent(e);
  84. redrawMarks();
  85. }
  86. void KateScrollBar::resizeEvent(TQResizeEvent *e)
  87. {
  88. TQScrollBar::resizeEvent(e);
  89. recomputeMarksPositions();
  90. }
  91. void KateScrollBar::styleChange(TQStyle &s)
  92. {
  93. TQScrollBar::styleChange(s);
  94. m_topMargin = -1;
  95. recomputeMarksPositions();
  96. }
  97. void KateScrollBar::valueChange()
  98. {
  99. TQScrollBar::valueChange();
  100. redrawMarks();
  101. }
  102. void KateScrollBar::rangeChange()
  103. {
  104. TQScrollBar::rangeChange();
  105. recomputeMarksPositions();
  106. }
  107. void KateScrollBar::marksChanged()
  108. {
  109. recomputeMarksPositions(true);
  110. }
  111. void KateScrollBar::redrawMarks()
  112. {
  113. if (!m_showMarks)
  114. return;
  115. TQPainter painter(this);
  116. TQRect rect = sliderRect();
  117. for (TQIntDictIterator<TQColor> it(m_lines); it.current(); ++it)
  118. {
  119. if (it.currentKey() < rect.top() || it.currentKey() > rect.bottom())
  120. {
  121. painter.setPen(*it.current());
  122. painter.drawLine(0, it.currentKey(), width(), it.currentKey());
  123. }
  124. }
  125. }
  126. void KateScrollBar::recomputeMarksPositions(bool forceFullUpdate)
  127. {
  128. if (m_topMargin == -1)
  129. watchScrollBarSize();
  130. m_lines.clear();
  131. m_savVisibleLines = m_doc->visibleLines();
  132. int realHeight = frameGeometry().height() - m_topMargin - m_bottomMargin;
  133. TQPtrList<KTextEditor::Mark> marks = m_doc->marks();
  134. KateCodeFoldingTree *tree = m_doc->foldingTree();
  135. for (KTextEditor::Mark *mark = marks.first(); mark; mark = marks.next())
  136. {
  137. uint line = mark->line;
  138. if (tree)
  139. {
  140. KateCodeFoldingNode *node = tree->findNodeForLine(line);
  141. while (node)
  142. {
  143. if (!node->isVisible())
  144. line = tree->getStartLine(node);
  145. node = node->getParentNode();
  146. }
  147. }
  148. line = m_doc->getVirtualLine(line);
  149. double d = (double)line / (m_savVisibleLines - 1);
  150. m_lines.insert(m_topMargin + (int)(d * realHeight),
  151. new TQColor(KateRendererConfig::global()->lineMarkerColor((KTextEditor::MarkInterface::MarkTypes)mark->type)));
  152. }
  153. if (forceFullUpdate)
  154. update();
  155. else
  156. redrawMarks();
  157. }
  158. void KateScrollBar::watchScrollBarSize()
  159. {
  160. int savMax = maxValue();
  161. setMaxValue(0);
  162. TQRect rect = sliderRect();
  163. setMaxValue(savMax);
  164. m_topMargin = rect.top();
  165. m_bottomMargin = frameGeometry().height() - rect.bottom();
  166. }
  167. void KateScrollBar::sliderMaybeMoved(int value)
  168. {
  169. if (m_middleMouseDown)
  170. emit sliderMMBMoved(value);
  171. }
  172. //END
  173. //BEGIN KateCmdLnWhatsThis
  174. class KateCmdLnWhatsThis : public TQWhatsThis
  175. {
  176. public:
  177. KateCmdLnWhatsThis( KateCmdLine *parent )
  178. : TQWhatsThis( parent )
  179. , m_parent( parent ) {;}
  180. TQString text( const TQPoint & )
  181. {
  182. TQString beg = "<qt background=\"white\"><div><table width=\"100%\"><tr><td bgcolor=\"brown\"><font color=\"white\"><b>Help: <big>";
  183. TQString mid = "</big></b></font></td></tr><tr><td>";
  184. TQString end = "</td></tr></table></div><qt>";
  185. TQString t = m_parent->text();
  186. TQRegExp re( "\\s*help\\s+(.*)" );
  187. if ( re.search( t ) > -1 )
  188. {
  189. TQString s;
  190. // get help for command
  191. TQString name = re.cap( 1 );
  192. if ( name == "list" )
  193. {
  194. return beg + i18n("Available Commands") + mid
  195. + KateCmd::self()->cmds().join(" ")
  196. + i18n("<p>For help on individual commands, do <code>'help &lt;command&gt;'</code></p>")
  197. + end;
  198. }
  199. else if ( ! name.isEmpty() )
  200. {
  201. Kate::Command *cmd = KateCmd::self()->queryCommand( name );
  202. if ( cmd )
  203. {
  204. if ( cmd->help( (Kate::View*)m_parent->parentWidget(), name, s ) )
  205. return beg + name + mid + s + end;
  206. else
  207. return beg + name + mid + i18n("No help for '%1'").arg( name ) + end;
  208. }
  209. else
  210. return beg + mid + i18n("No such command <b>%1</b>").arg(name) + end;
  211. }
  212. }
  213. return beg + mid + i18n(
  214. "<p>This is the Katepart <b>command line</b>.<br>"
  215. "Syntax: <code><b>command [ arguments ]</b></code><br>"
  216. "For a list of available commands, enter <code><b>help list</b></code><br>"
  217. "For help for individual commands, enter <code><b>help &lt;command&gt;</b></code></p>")
  218. + end;
  219. }
  220. private:
  221. KateCmdLine *m_parent;
  222. };
  223. //END KateCmdLnWhatsThis
  224. //BEGIN KateCmdLineFlagCompletion
  225. /**
  226. * This class provide completion of flags. It shows a short description of
  227. * each flag, and flags are appended.
  228. */
  229. class KateCmdLineFlagCompletion : public TDECompletion
  230. {
  231. public:
  232. KateCmdLineFlagCompletion() {;}
  233. TQString makeCompletion( const TQString & string )
  234. {
  235. return TQString::null;
  236. }
  237. };
  238. //END KateCmdLineFlagCompletion
  239. //BEGIN KateCmdLine
  240. KateCmdLine::KateCmdLine (KateView *view)
  241. : KLineEdit (view)
  242. , m_view (view)
  243. , m_msgMode (false)
  244. , m_histpos( 0 )
  245. , m_cmdend( 0 )
  246. , m_command( 0L )
  247. , m_oldCompletionObject( 0L )
  248. {
  249. connect (this, TQT_SIGNAL(returnPressed(const TQString &)),
  250. this, TQT_SLOT(slotReturnPressed(const TQString &)));
  251. completionObject()->insertItems (KateCmd::self()->cmds());
  252. setAutoDeleteCompletionObject( false );
  253. m_help = new KateCmdLnWhatsThis( this );
  254. }
  255. void KateCmdLine::slotReturnPressed ( const TQString& text )
  256. {
  257. // silently ignore leading space
  258. uint n = 0;
  259. while( text[n].isSpace() )
  260. n++;
  261. TQString cmd = text.mid( n );
  262. // Built in help: if the command starts with "help", [try to] show some help
  263. if ( cmd.startsWith( "help" ) )
  264. {
  265. m_help->display( m_help->text( TQPoint() ), mapToGlobal(TQPoint(0,0)) );
  266. clear();
  267. KateCmd::self()->appendHistory( cmd );
  268. m_histpos = KateCmd::self()->historyLength();
  269. m_oldText = TQString ();
  270. return;
  271. }
  272. if (cmd.length () > 0)
  273. {
  274. Kate::Command *p = KateCmd::self()->queryCommand (cmd);
  275. m_oldText = cmd;
  276. m_msgMode = true;
  277. if (p)
  278. {
  279. TQString msg;
  280. if (p->exec (m_view, cmd, msg))
  281. {
  282. KateCmd::self()->appendHistory( cmd );
  283. m_histpos = KateCmd::self()->historyLength();
  284. m_oldText = TQString ();
  285. if (msg.length() > 0)
  286. setText (i18n ("Success: ") + msg);
  287. else
  288. setText (i18n ("Success"));
  289. }
  290. else
  291. {
  292. if (msg.length() > 0)
  293. setText (i18n ("Error: ") + msg);
  294. else
  295. setText (i18n ("Command \"%1\" failed.").arg (cmd));
  296. KNotifyClient::beep();
  297. }
  298. }
  299. else
  300. {
  301. setText (i18n ("No such command: \"%1\"").arg (cmd));
  302. KNotifyClient::beep();
  303. }
  304. }
  305. // clean up
  306. if ( m_oldCompletionObject )
  307. {
  308. TDECompletion *c = completionObject();
  309. setCompletionObject( m_oldCompletionObject );
  310. m_oldCompletionObject = 0;
  311. delete c;
  312. c = 0;
  313. }
  314. m_command = 0;
  315. m_cmdend = 0;
  316. m_view->setFocus ();
  317. TQTimer::singleShot( 4000, this, TQT_SLOT(hideMe()) );
  318. }
  319. void KateCmdLine::hideMe () // unless i have focus ;)
  320. {
  321. if ( isVisibleTo(parentWidget()) && ! hasFocus() ) {
  322. m_view->toggleCmdLine ();
  323. }
  324. }
  325. void KateCmdLine::focusInEvent ( TQFocusEvent *ev )
  326. {
  327. if (m_msgMode)
  328. {
  329. m_msgMode = false;
  330. setText (m_oldText);
  331. selectAll();
  332. }
  333. KLineEdit::focusInEvent (ev);
  334. }
  335. void KateCmdLine::keyPressEvent( TQKeyEvent *ev )
  336. {
  337. if (ev->key() == Key_Escape)
  338. {
  339. m_view->setFocus ();
  340. hideMe();
  341. }
  342. else if ( ev->key() == Key_Up )
  343. fromHistory( true );
  344. else if ( ev->key() == Key_Down )
  345. fromHistory( false );
  346. uint cursorpos = cursorPosition();
  347. KLineEdit::keyPressEvent (ev);
  348. // during typing, let us see if we have a valid command
  349. if ( ! m_cmdend || cursorpos <= m_cmdend )
  350. {
  351. TQChar c;
  352. if ( ! ev->text().isEmpty() )
  353. c = ev->text()[0];
  354. if ( ! m_cmdend && ! c.isNull() ) // we have no command, so lets see if we got one
  355. {
  356. if ( ! c.isLetterOrNumber() && c != '-' && c != '_' )
  357. {
  358. m_command = KateCmd::self()->queryCommand( text().stripWhiteSpace() );
  359. if ( m_command )
  360. {
  361. //kdDebug(13025)<<"keypress in commandline: We have a command! "<<m_command<<". text is '"<<text()<<"'"<<endl;
  362. // if the typed character is ":",
  363. // we try if the command has flag completions
  364. m_cmdend = cursorpos;
  365. //kdDebug(13025)<<"keypress in commandline: Set m_cmdend to "<<m_cmdend<<endl;
  366. }
  367. else
  368. m_cmdend = 0;
  369. }
  370. }
  371. else // since cursor is inside the command name, we reconsider it
  372. {
  373. kdDebug(13025)<<"keypress in commandline: \\W -- text is "<<text()<<endl;
  374. m_command = KateCmd::self()->queryCommand( text().stripWhiteSpace() );
  375. if ( m_command )
  376. {
  377. //kdDebug(13025)<<"keypress in commandline: We have a command! "<<m_command<<endl;
  378. TQString t = text();
  379. m_cmdend = 0;
  380. bool b = false;
  381. for ( ; m_cmdend < t.length(); m_cmdend++ )
  382. {
  383. if ( t[m_cmdend].isLetter() )
  384. b = true;
  385. if ( b && ( ! t[m_cmdend].isLetterOrNumber() && t[m_cmdend] != '-' && t[m_cmdend] != '_' ) )
  386. break;
  387. }
  388. if ( c == ':' && cursorpos == m_cmdend )
  389. {
  390. // check if this command wants to complete flags
  391. //kdDebug(13025)<<"keypress in commandline: Checking if flag completion is desired!"<<endl;
  392. }
  393. }
  394. else
  395. {
  396. // clean up if needed
  397. if ( m_oldCompletionObject )
  398. {
  399. TDECompletion *c = completionObject();
  400. setCompletionObject( m_oldCompletionObject );
  401. m_oldCompletionObject = 0;
  402. delete c;
  403. c = 0;
  404. }
  405. m_cmdend = 0;
  406. }
  407. }
  408. // if we got a command, check if it wants to do semething.
  409. if ( m_command )
  410. {
  411. //kdDebug(13025)<<"Checking for CommandExtension.."<<endl;
  412. Kate::CommandExtension *ce = dynamic_cast<Kate::CommandExtension*>(m_command);
  413. if ( ce )
  414. {
  415. TDECompletion *cmpl = ce->completionObject( text().left( m_cmdend ).stripWhiteSpace(), m_view );
  416. if ( cmpl )
  417. {
  418. // save the old completion object and use what the command provides
  419. // instead. We also need to prepend the current command name + flag string
  420. // when completion is done
  421. //kdDebug(13025)<<"keypress in commandline: Setting completion object!"<<endl;
  422. if ( ! m_oldCompletionObject )
  423. m_oldCompletionObject = completionObject();
  424. setCompletionObject( cmpl );
  425. }
  426. }
  427. }
  428. }
  429. else if ( m_command )// check if we should call the commands processText()
  430. {
  431. Kate::CommandExtension *ce = dynamic_cast<Kate::CommandExtension*>( m_command );
  432. if ( ce && ce->wantsToProcessText( text().left( m_cmdend ).stripWhiteSpace() )
  433. && ! ( ev->text().isNull() || ev->text().isEmpty() ) )
  434. ce->processText( m_view, text() );
  435. }
  436. }
  437. void KateCmdLine::fromHistory( bool up )
  438. {
  439. if ( ! KateCmd::self()->historyLength() )
  440. return;
  441. TQString s;
  442. if ( up )
  443. {
  444. if ( m_histpos > 0 )
  445. {
  446. m_histpos--;
  447. s = KateCmd::self()->fromHistory( m_histpos );
  448. }
  449. }
  450. else
  451. {
  452. if ( m_histpos < ( KateCmd::self()->historyLength() - 1 ) )
  453. {
  454. m_histpos++;
  455. s = KateCmd::self()->fromHistory( m_histpos );
  456. }
  457. else
  458. {
  459. m_histpos = KateCmd::self()->historyLength();
  460. setText( m_oldText );
  461. }
  462. }
  463. if ( ! s.isEmpty() )
  464. {
  465. // Select the argument part of the command, so that it is easy to overwrite
  466. setText( s );
  467. static TQRegExp reCmd = TQRegExp(".*[\\w\\-]+(?:[^a-zA-Z0-9_-]|:\\w+)(.*)");
  468. if ( reCmd.search( text() ) == 0 )
  469. setSelection( text().length() - reCmd.cap(1).length(), reCmd.cap(1).length() );
  470. }
  471. }
  472. //END KateCmdLine
  473. //BEGIN KateIconBorder
  474. using namespace KTextEditor;
  475. static const char* const plus_xpm[] = {
  476. "11 11 3 1",
  477. " c None",
  478. ". c #000000",
  479. "+ c #FFFFFF",
  480. "...........",
  481. ".+++++++++.",
  482. ".+++++++++.",
  483. ".++++.++++.",
  484. ".++++.++++.",
  485. ".++.....++.",
  486. ".++++.++++.",
  487. ".++++.++++.",
  488. ".+++++++++.",
  489. ".+++++++++.",
  490. "..........."};
  491. static const char* const minus_xpm[] = {
  492. "11 11 3 1",
  493. " c None",
  494. ". c #000000",
  495. "+ c #FFFFFF",
  496. "...........",
  497. ".+++++++++.",
  498. ".+++++++++.",
  499. ".+++++++++.",
  500. ".+++++++++.",
  501. ".++.....++.",
  502. ".+++++++++.",
  503. ".+++++++++.",
  504. ".+++++++++.",
  505. ".+++++++++.",
  506. "..........."};
  507. static const char * const bookmark_xpm[] = {
  508. "14 13 82 1",
  509. " c None",
  510. ". c #F27D01",
  511. "+ c #EF7901",
  512. "@ c #F3940F",
  513. "# c #EE8F12",
  514. "$ c #F9C834",
  515. "% c #F5C33A",
  516. "& c #F09110",
  517. "* c #FCEE3E",
  518. "= c #FBEB3F",
  519. "- c #E68614",
  520. "; c #FA8700",
  521. "> c #F78703",
  522. ", c #F4920E",
  523. "' c #F19113",
  524. ") c #F6C434",
  525. "! c #FDF938",
  526. "~ c #FDF839",
  527. "{ c #F1BC3A",
  528. "] c #E18017",
  529. "^ c #DA7210",
  530. "/ c #D5680B",
  531. "( c #CA5404",
  532. "_ c #FD8F06",
  533. ": c #FCB62D",
  534. "< c #FDE049",
  535. "[ c #FCE340",
  536. "} c #FBE334",
  537. "| c #FDF035",
  538. "1 c #FEF834",
  539. "2 c #FCEF36",
  540. "3 c #F8DF32",
  541. "4 c #F7DC3D",
  542. "5 c #F5CE3E",
  543. "6 c #DE861B",
  544. "7 c #C64C03",
  545. "8 c #F78C07",
  546. "9 c #F8B019",
  547. "0 c #FDE12D",
  548. "a c #FEE528",
  549. "b c #FEE229",
  550. "c c #FBD029",
  551. "d c #E18814",
  552. "e c #CB5605",
  553. "f c #EF8306",
  554. "g c #F3A00E",
  555. "h c #FBC718",
  556. "i c #FED31C",
  557. "j c #FED11D",
  558. "k c #F8B91C",
  559. "l c #E07D0D",
  560. "m c #CB5301",
  561. "n c #ED8A0E",
  562. "o c #F7A90D",
  563. "p c #FEC113",
  564. "q c #FEC013",
  565. "r c #F09B0E",
  566. "s c #D35E03",
  567. "t c #EF9213",
  568. "u c #F9A208",
  569. "v c #FEAA0C",
  570. "w c #FCA10B",
  571. "x c #FCA70B",
  572. "y c #FEAF0B",
  573. "z c #F39609",
  574. "A c #D86203",
  575. "B c #F08C0D",
  576. "C c #FA9004",
  577. "D c #F17F04",
  578. "E c #E36D04",
  579. "F c #E16F03",
  580. "G c #EE8304",
  581. "H c #F88C04",
  582. "I c #DC6202",
  583. "J c #E87204",
  584. "K c #E66A01",
  585. "L c #DC6001",
  586. "M c #D15601",
  587. "N c #DA5D01",
  588. "O c #D25200",
  589. "P c #DA5F00",
  590. "Q c #BC3C00",
  591. " .+ ",
  592. " @# ",
  593. " $% ",
  594. " &*=- ",
  595. " ;>,')!~{]^/( ",
  596. "_:<[}|11234567",
  597. " 890aaaaabcde ",
  598. " fghiiijklm ",
  599. " nopqpqrs ",
  600. " tuvwxyzA ",
  601. " BCDEFGHI ",
  602. " JKL MNO ",
  603. " P Q "};
  604. const int iconPaneWidth = 16;
  605. const int halfIPW = 8;
  606. KateIconBorder::KateIconBorder ( KateViewInternal* internalView, TQWidget *parent )
  607. : TQWidget(parent, "", (WFlags)(WStaticContents | WRepaintNoErase | WResizeNoErase) )
  608. , m_view( internalView->m_view )
  609. , m_doc( internalView->m_doc )
  610. , m_viewInternal( internalView )
  611. , m_iconBorderOn( false )
  612. , m_lineNumbersOn( false )
  613. , m_foldingMarkersOn( false )
  614. , m_dynWrapIndicatorsOn( false )
  615. , m_dynWrapIndicators( 0 )
  616. , m_cachedLNWidth( 0 )
  617. , m_maxCharWidth( 0 )
  618. {
  619. setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Minimum ) );
  620. setBackgroundMode( NoBackground );
  621. m_doc->setDescription( MarkInterface::markType01, i18n("Bookmark") );
  622. m_doc->setPixmap( MarkInterface::markType01, TQPixmap((const char**)bookmark_xpm) );
  623. updateFont();
  624. }
  625. void KateIconBorder::setIconBorderOn( bool enable )
  626. {
  627. if( enable == m_iconBorderOn )
  628. return;
  629. m_iconBorderOn = enable;
  630. updateGeometry();
  631. TQTimer::singleShot( 0, this, TQT_SLOT(update()) );
  632. }
  633. void KateIconBorder::setLineNumbersOn( bool enable )
  634. {
  635. if( enable == m_lineNumbersOn )
  636. return;
  637. m_lineNumbersOn = enable;
  638. m_dynWrapIndicatorsOn = (m_dynWrapIndicators == 1) ? enable : m_dynWrapIndicators;
  639. updateGeometry();
  640. TQTimer::singleShot( 0, this, TQT_SLOT(update()) );
  641. }
  642. void KateIconBorder::setDynWrapIndicators( int state )
  643. {
  644. if (state == m_dynWrapIndicators )
  645. return;
  646. m_dynWrapIndicators = state;
  647. m_dynWrapIndicatorsOn = (state == 1) ? m_lineNumbersOn : state;
  648. updateGeometry ();
  649. TQTimer::singleShot( 0, this, TQT_SLOT(update()) );
  650. }
  651. void KateIconBorder::setFoldingMarkersOn( bool enable )
  652. {
  653. if( enable == m_foldingMarkersOn )
  654. return;
  655. m_foldingMarkersOn = enable;
  656. updateGeometry();
  657. TQTimer::singleShot( 0, this, TQT_SLOT(update()) );
  658. }
  659. TQSize KateIconBorder::sizeHint() const
  660. {
  661. int w = 0;
  662. if (m_iconBorderOn)
  663. w += iconPaneWidth + 1;
  664. if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) {
  665. w += lineNumberWidth();
  666. }
  667. if (m_foldingMarkersOn)
  668. w += iconPaneWidth;
  669. w += 4;
  670. return TQSize( w, 0 );
  671. }
  672. // This function (re)calculates the maximum width of any of the digit characters (0 -> 9)
  673. // for graceful handling of variable-width fonts as the linenumber font.
  674. void KateIconBorder::updateFont()
  675. {
  676. const TQFontMetrics *fm = m_view->renderer()->config()->fontMetrics();
  677. m_maxCharWidth = 0;
  678. // Loop to determine the widest numeric character in the current font.
  679. // 48 is ascii '0'
  680. for (int i = 48; i < 58; i++) {
  681. int charWidth = fm->width( TQChar(i) );
  682. m_maxCharWidth = kMax(m_maxCharWidth, charWidth);
  683. }
  684. }
  685. int KateIconBorder::lineNumberWidth() const
  686. {
  687. int width = m_lineNumbersOn ? ((int)log10((double)(m_view->doc()->numLines())) + 1) * m_maxCharWidth + 4 : 0;
  688. if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
  689. width = kMax(style().scrollBarExtent().width() + 4, width);
  690. if (m_cachedLNWidth != width || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) {
  691. int w = style().scrollBarExtent().width();
  692. int h = m_view->renderer()->config()->fontMetrics()->height();
  693. TQSize newSize(w, h);
  694. if ((m_arrow.size() != newSize || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) && !newSize.isEmpty()) {
  695. m_arrow.resize(newSize);
  696. TQPainter p(&m_arrow);
  697. p.fillRect( 0, 0, w, h, m_view->renderer()->config()->iconBarColor() );
  698. h = m_view->renderer()->config()->fontMetrics()->ascent();
  699. p.setPen(m_view->renderer()->attribute(0)->textColor());
  700. p.drawLine(w/2, h/2, w/2, 0);
  701. #if 1
  702. p.lineTo(w/4, h/4);
  703. p.lineTo(0, 0);
  704. p.lineTo(0, h/2);
  705. p.lineTo(w/2, h-1);
  706. p.lineTo(w*3/4, h-1);
  707. p.lineTo(w-1, h*3/4);
  708. p.lineTo(w*3/4, h/2);
  709. p.lineTo(0, h/2);
  710. #else
  711. p.lineTo(w*3/4, h/4);
  712. p.lineTo(w-1,0);
  713. p.lineTo(w-1, h/2);
  714. p.lineTo(w/2, h-1);
  715. p.lineTo(w/4,h-1);
  716. p.lineTo(0, h*3/4);
  717. p.lineTo(w/4, h/2);
  718. p.lineTo(w-1, h/2);
  719. #endif
  720. }
  721. }
  722. }
  723. return width;
  724. }
  725. void KateIconBorder::paintEvent(TQPaintEvent* e)
  726. {
  727. paintBorder(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
  728. }
  729. void KateIconBorder::paintBorder (int /*x*/, int y, int /*width*/, int height)
  730. {
  731. static TQPixmap minus_px ((const char**)minus_xpm);
  732. static TQPixmap plus_px ((const char**)plus_xpm);
  733. uint h = m_view->renderer()->config()->fontStruct()->fontHeight;
  734. uint startz = (y / h);
  735. uint endz = startz + 1 + (height / h);
  736. uint lineRangesSize = m_viewInternal->lineRanges.size();
  737. // center the folding boxes
  738. int m_px = (h - 11) / 2;
  739. if (m_px < 0)
  740. m_px = 0;
  741. int lnWidth( 0 );
  742. if ( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) ) // avoid calculating unless needed ;-)
  743. {
  744. lnWidth = lineNumberWidth();
  745. if ( lnWidth != m_cachedLNWidth || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor() )
  746. {
  747. // we went from n0 ->n9 lines or vice verca
  748. // this causes an extra updateGeometry() first time the line numbers
  749. // are displayed, but sizeHint() is supposed to be const so we can't set
  750. // the cached value there.
  751. m_cachedLNWidth = lnWidth;
  752. m_oldBackgroundColor = m_view->renderer()->config()->iconBarColor();
  753. updateGeometry();
  754. update ();
  755. return;
  756. }
  757. }
  758. int w( this->width() ); // sane value/calc only once
  759. TQPainter p ( this );
  760. p.setFont ( *m_view->renderer()->config()->font() ); // for line numbers
  761. // the line number color is for the line numbers, vertical separator lines
  762. // and for for the code folding lines.
  763. p.setPen ( m_view->renderer()->config()->lineNumberColor() );
  764. KateLineInfo oldInfo;
  765. if (startz < lineRangesSize)
  766. {
  767. if ((m_viewInternal->lineRanges[startz].line-1) < 0)
  768. oldInfo.topLevel = true;
  769. else
  770. m_doc->lineInfo(&oldInfo,m_viewInternal->lineRanges[startz].line-1);
  771. }
  772. for (uint z=startz; z <= endz; z++)
  773. {
  774. int y = h * z;
  775. int realLine = -1;
  776. if (z < lineRangesSize)
  777. realLine = m_viewInternal->lineRanges[z].line;
  778. int lnX ( 0 );
  779. p.fillRect( 0, y, w-4, h, m_view->renderer()->config()->iconBarColor() );
  780. p.fillRect( w-4, y, 4, h, m_view->renderer()->config()->backgroundColor() );
  781. // icon pane
  782. if( m_iconBorderOn )
  783. {
  784. p.drawLine(lnX+iconPaneWidth, y, lnX+iconPaneWidth, y+h);
  785. if( (realLine > -1) && (m_viewInternal->lineRanges[z].startCol == 0) )
  786. {
  787. uint mrk ( m_doc->mark( realLine ) ); // call only once
  788. if ( mrk )
  789. {
  790. for( uint bit = 0; bit < 32; bit++ )
  791. {
  792. MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
  793. if( mrk & markType )
  794. {
  795. TQPixmap *px_mark (m_doc->markPixmap( markType ));
  796. if (px_mark)
  797. {
  798. // center the mark pixmap
  799. int x_px = (iconPaneWidth - px_mark->width()) / 2;
  800. if (x_px < 0)
  801. x_px = 0;
  802. int y_px = (h - px_mark->height()) / 2;
  803. if (y_px < 0)
  804. y_px = 0;
  805. p.drawPixmap( lnX+x_px, y+y_px, *px_mark);
  806. }
  807. }
  808. }
  809. }
  810. }
  811. lnX += iconPaneWidth + 1;
  812. }
  813. // line number
  814. if( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) )
  815. {
  816. lnX +=2;
  817. if (realLine > -1)
  818. if (m_viewInternal->lineRanges[z].startCol == 0) {
  819. if (m_lineNumbersOn)
  820. p.drawText( lnX + 1, y, lnWidth-4, h, Qt::AlignRight|Qt::AlignVCenter, TQString("%1").arg( realLine + 1 ) );
  821. } else if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
  822. p.drawPixmap(lnX + lnWidth - m_arrow.width() - 4, y, m_arrow);
  823. }
  824. lnX += lnWidth;
  825. }
  826. // folding markers
  827. if( m_foldingMarkersOn )
  828. {
  829. if( realLine > -1 )
  830. {
  831. KateLineInfo info;
  832. m_doc->lineInfo(&info,realLine);
  833. if (!info.topLevel)
  834. {
  835. if (info.startsVisibleBlock && (m_viewInternal->lineRanges[z].startCol == 0))
  836. {
  837. if (oldInfo.topLevel)
  838. p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1);
  839. else
  840. p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
  841. p.drawPixmap(lnX+3,y+m_px,minus_px);
  842. }
  843. else if (info.startsInVisibleBlock)
  844. {
  845. if (m_viewInternal->lineRanges[z].startCol == 0)
  846. {
  847. if (oldInfo.topLevel)
  848. p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1);
  849. else
  850. p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
  851. p.drawPixmap(lnX+3,y+m_px,plus_px);
  852. }
  853. else
  854. {
  855. p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
  856. }
  857. if (!m_viewInternal->lineRanges[z].wrap)
  858. p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1);
  859. }
  860. else
  861. {
  862. p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
  863. if (info.endsBlock && !m_viewInternal->lineRanges[z].wrap)
  864. p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1);
  865. }
  866. }
  867. oldInfo = info;
  868. }
  869. lnX += iconPaneWidth;
  870. }
  871. }
  872. }
  873. KateIconBorder::BorderArea KateIconBorder::positionToArea( const TQPoint& p ) const
  874. {
  875. int x = 0;
  876. if( m_iconBorderOn ) {
  877. x += iconPaneWidth;
  878. if( p.x() <= x )
  879. return IconBorder;
  880. }
  881. if( m_lineNumbersOn || m_dynWrapIndicators ) {
  882. x += lineNumberWidth();
  883. if( p.x() <= x )
  884. return LineNumbers;
  885. }
  886. if( m_foldingMarkersOn ) {
  887. x += iconPaneWidth;
  888. if( p.x() <= x )
  889. return FoldingMarkers;
  890. }
  891. return None;
  892. }
  893. void KateIconBorder::mousePressEvent( TQMouseEvent* e )
  894. {
  895. m_lastClickedLine = m_viewInternal->yToKateLineRange(e->y()).line;
  896. if ( positionToArea( e->pos() ) != IconBorder )
  897. {
  898. TQMouseEvent forward( TQEvent::MouseButtonPress,
  899. TQPoint( 0, e->y() ), e->button(), e->state() );
  900. m_viewInternal->mousePressEvent( &forward );
  901. }
  902. e->accept();
  903. }
  904. void KateIconBorder::mouseMoveEvent( TQMouseEvent* e )
  905. {
  906. if ( positionToArea( e->pos() ) != IconBorder )
  907. {
  908. TQMouseEvent forward( TQEvent::MouseMove,
  909. TQPoint( 0, e->y() ), e->button(), e->state() );
  910. m_viewInternal->mouseMoveEvent( &forward );
  911. }
  912. }
  913. void KateIconBorder::mouseReleaseEvent( TQMouseEvent* e )
  914. {
  915. uint cursorOnLine = m_viewInternal->yToKateLineRange(e->y()).line;
  916. if (cursorOnLine == m_lastClickedLine &&
  917. cursorOnLine <= m_doc->lastLine() )
  918. {
  919. BorderArea area = positionToArea( e->pos() );
  920. if( area == IconBorder) {
  921. if (e->button() == Qt::LeftButton) {
  922. if( m_doc->editableMarks() & KateViewConfig::global()->defaultMarkType() ) {
  923. if( m_doc->mark( cursorOnLine ) & KateViewConfig::global()->defaultMarkType() )
  924. m_doc->removeMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
  925. else
  926. m_doc->addMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
  927. } else {
  928. showMarkMenu( cursorOnLine, TQCursor::pos() );
  929. }
  930. }
  931. else
  932. if (e->button() == Qt::RightButton) {
  933. showMarkMenu( cursorOnLine, TQCursor::pos() );
  934. }
  935. }
  936. if ( area == FoldingMarkers) {
  937. KateLineInfo info;
  938. m_doc->lineInfo(&info,cursorOnLine);
  939. if ((info.startsVisibleBlock) || (info.startsInVisibleBlock)) {
  940. emit toggleRegionVisibility(cursorOnLine);
  941. }
  942. }
  943. }
  944. TQMouseEvent forward( TQEvent::MouseButtonRelease,
  945. TQPoint( 0, e->y() ), e->button(), e->state() );
  946. m_viewInternal->mouseReleaseEvent( &forward );
  947. }
  948. void KateIconBorder::mouseDoubleClickEvent( TQMouseEvent* e )
  949. {
  950. TQMouseEvent forward( TQEvent::MouseButtonDblClick,
  951. TQPoint( 0, e->y() ), e->button(), e->state() );
  952. m_viewInternal->mouseDoubleClickEvent( &forward );
  953. }
  954. void KateIconBorder::showMarkMenu( uint line, const TQPoint& pos )
  955. {
  956. TQPopupMenu markMenu;
  957. TQPopupMenu selectDefaultMark;
  958. typedef TQValueVector<int> MarkTypeVector;
  959. MarkTypeVector vec( 33 );
  960. int i=1;
  961. for( uint bit = 0; bit < 32; bit++ ) {
  962. MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
  963. if( !(m_doc->editableMarks() & markType) )
  964. continue;
  965. if( !m_doc->markDescription( markType ).isEmpty() ) {
  966. markMenu.insertItem( m_doc->markDescription( markType ), i );
  967. selectDefaultMark.insertItem( m_doc->markDescription( markType ), i+100);
  968. } else {
  969. markMenu.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i );
  970. selectDefaultMark.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i+100);
  971. }
  972. if( m_doc->mark( line ) & markType )
  973. markMenu.setItemChecked( i, true );
  974. if( markType & KateViewConfig::global()->defaultMarkType() )
  975. selectDefaultMark.setItemChecked( i+100, true );
  976. vec[i++] = markType;
  977. }
  978. if( markMenu.count() == 0 )
  979. return;
  980. if( markMenu.count() > 1 )
  981. markMenu.insertItem( i18n("Set Default Mark Type" ), &selectDefaultMark);
  982. int result = markMenu.exec( pos );
  983. if( result <= 0 )
  984. return;
  985. if ( result > 100)
  986. {
  987. KateViewConfig::global()->setDefaultMarkType (vec[result-100]);
  988. // flush config, otherwise it isn't nessecarily done
  989. TDEConfig *config = kapp->config();
  990. config->setGroup("Kate View Defaults");
  991. KateViewConfig::global()->writeConfig( config );
  992. }
  993. else
  994. {
  995. MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes) vec[result];
  996. if( m_doc->mark( line ) & markType ) {
  997. m_doc->removeMark( line, markType );
  998. } else {
  999. m_doc->addMark( line, markType );
  1000. }
  1001. }
  1002. }
  1003. //END KateIconBorder
  1004. KateViewEncodingAction::KateViewEncodingAction(KateDocument *_doc, KateView *_view, const TQString& text, TQObject* parent, const char* name)
  1005. : TDEActionMenu (text, parent, name), doc(_doc), view (_view)
  1006. {
  1007. connect(popupMenu(),TQT_SIGNAL(aboutToShow()),this,TQT_SLOT(slotAboutToShow()));
  1008. }
  1009. void KateViewEncodingAction::slotAboutToShow()
  1010. {
  1011. TQStringList modes (TDEGlobal::charsets()->descriptiveEncodingNames());
  1012. popupMenu()->clear ();
  1013. for (uint z=0; z<modes.size(); ++z)
  1014. {
  1015. popupMenu()->insertItem ( modes[z], this, TQT_SLOT(setMode(int)), 0, z);
  1016. bool found = false;
  1017. TQTextCodec *codecForEnc = TDEGlobal::charsets()->codecForName(TDEGlobal::charsets()->encodingForName(modes[z]), found);
  1018. if (found && codecForEnc)
  1019. {
  1020. if (codecForEnc->name() == doc->config()->codec()->name())
  1021. popupMenu()->setItemChecked (z, true);
  1022. }
  1023. }
  1024. }
  1025. void KateViewEncodingAction::setMode (int mode)
  1026. {
  1027. TQStringList modes (TDEGlobal::charsets()->descriptiveEncodingNames());
  1028. doc->config()->setEncoding( TDEGlobal::charsets()->encodingForName( modes[mode] ) );
  1029. // now we don't want the encoding changed again unless the user does so using the menu.
  1030. doc->setEncodingSticky( true );
  1031. doc->reloadFile();
  1032. }
  1033. // kate: space-indent on; indent-width 2; replace-tabs on;