srcfilewin.cpp 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368
  1. /*
  2. ktigcc - TIGCC IDE for KDE
  3. Copyright (C) 2004-2007 Kevin Kofler
  4. Copyright (C) 2006 Joey Adams
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software Foundation,
  15. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. */
  17. #include "srcfilewin.h"
  18. #include <qvariant.h>
  19. #include <qimage.h>
  20. #include <qpixmap.h>
  21. #include <qstring.h>
  22. #include <qregexp.h>
  23. #include <qapplication.h>
  24. #include <qlabel.h>
  25. #include <qstatusbar.h>
  26. #include <qtimer.h>
  27. #include <qdatetime.h>
  28. #include <q3dragobject.h>
  29. #include <qdir.h>
  30. #include <qclipboard.h>
  31. #include <q3accel.h>
  32. #include <qeventloop.h>
  33. #include <qlayout.h>
  34. #include <qtoolbutton.h>
  35. #include <q3listbox.h>
  36. #include <QKeyEvent>
  37. #include <q3mimefactory.h>
  38. #include <QResizeEvent>
  39. #include <Q3PopupMenu>
  40. #include <QEvent>
  41. #include <QCloseEvent>
  42. #include <QAssistantClient>
  43. #include <kparts/factory.h>
  44. #include <klibloader.h>
  45. #include <ktexteditor/editor.h>
  46. #include <ktexteditor/document.h>
  47. #include <ktexteditor/view.h>
  48. #include <ktexteditor/cursor.h>
  49. #include <ktexteditor/range.h>
  50. #include <ktexteditor/highlightinginterface.h>
  51. #include <ktexteditor/configinterface.h>
  52. #include <kconfig.h>
  53. #include <ktexteditor/configpage.h>
  54. #include <kfiledialog.h>
  55. #include <kurl.h>
  56. #include <kmessagebox.h>
  57. #include <kdirwatch.h>
  58. #include <kfinddialog.h>
  59. #include <kfind.h>
  60. #include <kreplacedialog.h>
  61. #include <kreplace.h>
  62. #include <kwin.h>
  63. #include <kicontheme.h>
  64. #include <kicon.h>
  65. #include <kiconloader.h>
  66. #include <kpushbutton.h>
  67. #include <kstandardaction.h>
  68. #include <cstdio>
  69. #include <cstdlib>
  70. #include "ktigcc.h"
  71. #include "mainform.h"
  72. #include "tpr.h"
  73. #include "preferences.h"
  74. #include "projectoptions.h"
  75. #include "srcfile.h"
  76. #include "functions.h"
  77. #include "completion.h"
  78. using std::puts;
  79. using std::exit;
  80. #define TIGCC_TPR_Filter "*.tpr|TIGCC Projects (*.tpr)\n"
  81. #define TIGCC_H_Filter "*.h|Header Files (*.h)\n"
  82. #define TIGCC_C_Filter "*.c|C Files (*.c)\n"
  83. #define TIGCC_S_Filter "*.s|GNU Assembly Files (*.s)\n"
  84. #define TIGCC_ASM_Filter "*.asm|A68k Assembly Files (*.asm)\n"
  85. #define TIGCC_QLL_Filter "*.qll|Quill Files (*.qll)\n"
  86. #define TIGCC_O_Filter "*.o|Object Files (*.o)\n"
  87. #define TIGCC_A_Filter "*.a|Archive Files (*.a)\n"
  88. #define TIGCC_TXT_Filter "*.txt|Text Files (*.txt)\n"
  89. #define TIGCCAllFilter "*|All Files (*)"
  90. enum {TIGCCOpenProjectFileFilter,TIGCCAddFilesFilter};
  91. #define THIS (static_cast<SourceFile *>(this))
  92. #define CURRENT_VIEW (THIS->kateView)
  93. #define HL_MODE ((THIS->hlEnabled && *(THIS->hlEnabled))?THIS->hlMode:"None")
  94. #define SET_TEXT_SAFE(doc,text) do { \
  95. disableViewEvents=TRUE; \
  96. (doc)->setText((text)); \
  97. disableViewEvents=FALSE; \
  98. } while(0)
  99. // For some reason, this flag is not in the public ConfigFlags enum.
  100. #define CF_REMOVE_TRAILING_DYN 0x4000000
  101. class KReplaceWithSelectionS : public KReplace {
  102. public:
  103. KReplaceWithSelectionS(const QString &pattern, const QString &replacement,
  104. long options, QWidget *parent=0) :
  105. KReplace(pattern,replacement,options,parent), m_haveSelection(FALSE) {}
  106. void setSelection(unsigned selStartLine, unsigned selStartCol,
  107. unsigned selEndLine, unsigned selEndCol)
  108. {
  109. m_haveSelection=TRUE;
  110. m_selStartLine=selStartLine;
  111. m_selStartCol=selStartCol;
  112. m_selEndLine=selEndLine;
  113. m_selEndCol=selEndCol;
  114. }
  115. int replaceCurrentLine;
  116. void invalidateSelection() {m_haveSelection=FALSE;}
  117. bool haveSelection() {return m_haveSelection;}
  118. int selStartLine() {return m_selStartLine;}
  119. int selStartCol() {return m_selStartCol;}
  120. int selEndLine() {return m_selEndLine;}
  121. int selEndCol() {return m_selEndCol;}
  122. // Override to ask for restarting when replacing in a selection.
  123. bool shouldRestart(bool forceAsking=FALSE, bool showNumMatches=TRUE)
  124. {
  125. return KReplace::shouldRestart(forceAsking||m_haveSelection,showNumMatches);
  126. }
  127. protected:
  128. virtual bool validateMatch(const QString &text, int index, int matchedlength)
  129. {
  130. if (!KReplace::validateMatch(text,index,matchedlength)) return FALSE;
  131. if (!m_haveSelection) return TRUE;
  132. if (replaceCurrentLine==m_selStartLine && replaceCurrentLine==m_selEndLine)
  133. return (index>=m_selStartCol)&&(index+matchedlength<=m_selEndCol);
  134. else if (replaceCurrentLine==m_selStartLine)
  135. return (index>=m_selStartCol);
  136. else if (replaceCurrentLine==m_selEndLine)
  137. return (index+matchedlength<=m_selEndCol);
  138. else
  139. return (replaceCurrentLine>=m_selStartLine&&replaceCurrentLine<=m_selEndLine);
  140. }
  141. private:
  142. bool m_haveSelection;
  143. int m_selStartLine, m_selStartCol, m_selEndLine, m_selEndCol;
  144. };
  145. void SourceFileWindow::initBase()
  146. {
  147. setIcon(qPixmapFromMimeSource("icon.png"));
  148. KWin::setIcons(winId(),*(icon()),qPixmapFromMimeSource("ktigcc.png"));
  149. sourceFiles.append(THIS);
  150. THIS->dirWatch=new KDirWatch(this);
  151. setCaption(caption()+" - "+THIS->fileName);
  152. THIS->te_popup = new Q3PopupMenu(this);
  153. THIS->te_popup->insertItem("&Open file at cursor",0);
  154. THIS->te_popup->insertItem("&Find symbol declaration",1);
  155. THIS->te_popup->insertSeparator();
  156. THIS->te_popup->insertItem("&Undo",2);
  157. THIS->te_popup->insertItem("&Redo",3);
  158. THIS->te_popup->insertSeparator();
  159. THIS->te_popup->insertItem("&Clear",4);
  160. THIS->te_popup->insertItem("Cu&t",5);
  161. THIS->te_popup->insertItem("Cop&y",6);
  162. THIS->te_popup->insertItem("&Paste",7);
  163. THIS->te_popup->insertSeparator();
  164. THIS->te_popup->insertItem("&Select all",8);
  165. THIS->te_popup->insertSeparator();
  166. THIS->te_popup->insertItem("&Increase indent",9);
  167. THIS->te_popup->insertItem("&Decrease indent",10);
  168. connect(THIS->te_popup,SIGNAL(aboutToShow()),this,SLOT(te_popup_aboutToShow()));
  169. connect(THIS->te_popup,SIGNAL(activated(int)),this,SLOT(te_popup_activated(int)));
  170. THIS->kfinddialog = static_cast<KFindDialog *>(NULL);
  171. THIS->kreplace = static_cast<KReplaceWithSelectionS *>(NULL);
  172. THIS->kateView=static_cast<KTextEditor::View *>(NULL);
  173. THIS->kateView=reinterpret_cast<KTextEditor::View *>(createView(THIS->fileName,THIS->fileText,HL_MODE,
  174. THIS->isASMFile?preferences.tabWidthAsm:THIS->isCFile?preferences.tabWidthC:8));
  175. THIS->fileText=QString::null;
  176. int rightStatusSize=size().width();
  177. int line, col;
  178. CURRENT_VIEW->cursorPosition().position(line,col);
  179. THIS->rowStatusLabel=new QLabel(QString("%1").arg(line+1),this);
  180. THIS->rowStatusLabel->setAlignment(Qt::AlignRight);
  181. THIS->rowStatusLabel->setMaximumWidth(30);
  182. statusBar()->addWidget(THIS->rowStatusLabel,1);
  183. THIS->colStatusLabel=new QLabel(QString("%1").arg(col+1),this);
  184. THIS->colStatusLabel->setAlignment(Qt::AlignRight);
  185. THIS->colStatusLabel->setMaximumWidth(30);
  186. statusBar()->addWidget(THIS->colStatusLabel,1);
  187. THIS->charsStatusLabel=new QLabel(QString("%1 Characters").arg(CURRENT_VIEW->document()->text().length()),this);
  188. THIS->charsStatusLabel->setMaximumWidth(100);
  189. statusBar()->addWidget(THIS->charsStatusLabel,1);
  190. THIS->rightStatusLabel=new QLabel(THIS->fileName,this);
  191. THIS->rightStatusLabel->setMaximumWidth(rightStatusSize-160>0?rightStatusSize-160:0);
  192. statusBar()->addWidget(THIS->rightStatusLabel,1);
  193. statusBar()->setSizeGripEnabled(FALSE);
  194. connect(statusBar(),SIGNAL(messageChanged(const QString &)),this,SLOT(statusBar_messageChanged(const QString &)));
  195. connect(THIS->dirWatch,SIGNAL(created(const QString &)),this,SLOT(KDirWatch_dirty(const QString &)));
  196. connect(THIS->dirWatch,SIGNAL(dirty(const QString &)),this,SLOT(KDirWatch_dirty(const QString &)));
  197. THIS->dirWatch->addFile(THIS->fileName);
  198. THIS->dirWatch->startScan();
  199. connect(clipboard,SIGNAL(dataChanged()),this,SLOT(clipboard_dataChanged()));
  200. centralWidget()->layout()->add(CURRENT_VIEW);
  201. CURRENT_VIEW->show();
  202. editUndoAction->setEnabled(CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Undo))->isEnabled());
  203. editRedoAction->setEnabled(CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Redo))->isEnabled());
  204. editClearAction->setEnabled(CURRENT_VIEW->selection());
  205. editCutAction->setEnabled(CURRENT_VIEW->selection());
  206. editCopyAction->setEnabled(CURRENT_VIEW->selection());
  207. editPasteAction->setEnabled(!clipboard->text().isNull());
  208. THIS->accel=new Q3Accel(this);
  209. THIS->accel->insertItem(Qt::ALT+Qt::Key_Backspace,0);
  210. THIS->accel->insertItem(Qt::SHIFT+Qt::ALT+Qt::Key_Backspace,1);
  211. THIS->accel->insertItem(Qt::SHIFT+Qt::Key_Delete,2);
  212. THIS->accel->insertItem(Qt::CTRL+Qt::Key_Insert,3);
  213. THIS->accel->insertItem(Qt::SHIFT+Qt::Key_Insert,4);
  214. THIS->accel->insertItem(Qt::Key_F1,5);
  215. THIS->accel->insertItem(Qt::Key_Enter,6);
  216. THIS->accel->insertItem(Qt::Key_Return,7);
  217. THIS->accel->insertItem(Qt::CTRL+Qt::Key_J,8);
  218. THIS->accel->insertItem(Qt::CTRL+Qt::Key_Space,9);
  219. THIS->accel->insertItem(Qt::CTRL+Qt::Key_M,10);
  220. THIS->accel->setItemEnabled(0,CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Undo))->isEnabled());
  221. THIS->accel->setItemEnabled(1,CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Redo))->isEnabled());
  222. THIS->accel->setItemEnabled(2,CURRENT_VIEW->selection());
  223. THIS->accel->setItemEnabled(3,CURRENT_VIEW->selection());
  224. THIS->accel->setItemEnabled(4,!clipboard->text().isNull());
  225. THIS->accel->setItemEnabled(5,TRUE);
  226. THIS->accel->setItemEnabled(6,TRUE);
  227. THIS->accel->setItemEnabled(7,TRUE);
  228. THIS->accel->setItemEnabled(8,TRUE);
  229. THIS->accel->setItemEnabled(9,TRUE);
  230. THIS->accel->setItemEnabled(10,TRUE);
  231. connect(THIS->accel,SIGNAL(activated(int)),this,SLOT(accel_activated(int)));
  232. if (preferences.useSystemIcons) {
  233. setUsesBigPixmaps(TRUE);
  234. fileSaveAction->setIconSet(KIcon("filesave"));
  235. fileAddToProjectAction->setIconSet(KIcon("edit_add"));
  236. fileCompileAction->setIconSet(KIcon("compfile"));
  237. filePrintAction->setIconSet(KIcon("fileprint"));
  238. filePrintQuicklyAction->setIconSet(KIcon("fileprint"));
  239. editClearAction->setIconSet(KIcon("editdelete"));
  240. editCutAction->setIconSet(KIcon("editcut"));
  241. editCopyAction->setIconSet(KIcon("editcopy"));
  242. editPasteAction->setIconSet(KIcon("editpaste"));
  243. findFindAction->setIconSet(KIcon("filefind"));
  244. if (KIconLoader::global()->iconPath("stock-find-and-replace",K3Icon::Small,TRUE).isEmpty())
  245. findReplaceAction->setIconSet(QIcon(qPixmapFromMimeSource("filereplace.png")));
  246. else
  247. findReplaceAction->setIconSet(KIcon("stock-find-and-replace"));
  248. editUndoAction->setIconSet(KIcon("undo"));
  249. editRedoAction->setIconSet(KIcon("redo"));
  250. findFunctionsAction->setIconSet(KIcon("view_tree"));
  251. editIncreaseIndentAction->setIconSet(KIcon("indent"));
  252. editDecreaseIndentAction->setIconSet(KIcon("unindent"));
  253. }
  254. QToolButton *findFunctionsButton=static_cast<QToolButton *>(toolBar
  255. ->child("findFunctionsAction_action_button","QToolButton",FALSE));
  256. THIS->findFunctionsPopup=new Q3PopupMenu(findFunctionsButton);
  257. connect(THIS->findFunctionsPopup,SIGNAL(aboutToShow()),
  258. this,SLOT(findFunctionsPopup_aboutToShow()));
  259. connect(THIS->findFunctionsPopup,SIGNAL(aboutToHide()),
  260. this,SLOT(findFunctionsPopup_aboutToHide()));
  261. connect(THIS->findFunctionsPopup,SIGNAL(activated(int)),
  262. this,SLOT(findFunctionsPopup_activated(int)));
  263. findFunctionsButton->setPopupDelay(0);
  264. findFunctionsButton->setPopup(THIS->findFunctionsPopup);
  265. if (THIS->isTextFile) findFunctionsAction->setEnabled(FALSE);
  266. }
  267. void SourceFileWindow::destroy()
  268. {
  269. MainForm::deleteErrorsForSrcFile(this);
  270. if (THIS->kreplace) delete THIS->kreplace;
  271. if (THIS->kfinddialog) {
  272. findHistory=THIS->kfinddialog->findHistory();
  273. delete THIS->kfinddialog;
  274. }
  275. delete THIS->accel;
  276. delete THIS->te_popup;
  277. delete THIS->rowStatusLabel;
  278. delete THIS->colStatusLabel;
  279. delete THIS->charsStatusLabel;
  280. delete THIS->rightStatusLabel;
  281. THIS->dirWatch->removeFile(THIS->fileName);
  282. delete THIS->dirWatch;
  283. if (THIS->kateView) delete THIS->kateView->document();
  284. sourceFiles.remove(THIS);
  285. }
  286. void SourceFileWindow::te_popup_aboutToShow()
  287. {
  288. THIS->te_popup->setItemEnabled(0,findOpenFileAtCursorAction->isEnabled());
  289. THIS->te_popup->setItemEnabled(1,findFindSymbolDeclarationAction->isEnabled());
  290. THIS->te_popup->setItemEnabled(2,editUndoAction->isEnabled());
  291. THIS->te_popup->setItemEnabled(3,editRedoAction->isEnabled());
  292. THIS->te_popup->setItemEnabled(4,editClearAction->isEnabled());
  293. THIS->te_popup->setItemEnabled(5,editCutAction->isEnabled());
  294. THIS->te_popup->setItemEnabled(6,editCopyAction->isEnabled());
  295. THIS->te_popup->setItemEnabled(7,editPasteAction->isEnabled());
  296. THIS->te_popup->setItemEnabled(8,editSelectAllAction->isEnabled());
  297. THIS->te_popup->setItemEnabled(9,editIncreaseIndentAction->isEnabled());
  298. THIS->te_popup->setItemEnabled(10,editDecreaseIndentAction->isEnabled());
  299. }
  300. void SourceFileWindow::te_popup_activated(int index)
  301. {
  302. switch (index) {
  303. case 0: findOpenFileAtCursor(); break;
  304. case 1: findFindSymbolDeclaration(); break;
  305. case 2: editUndo(); break;
  306. case 3: editRedo(); break;
  307. case 4: editClear(); break;
  308. case 5: editCut(); break;
  309. case 6: editCopy(); break;
  310. case 7: editPaste(); break;
  311. case 8: editSelectAll(); break;
  312. case 9: editIncreaseIndent(); break;
  313. case 10: editDecreaseIndent(); break;
  314. default: break;
  315. }
  316. }
  317. void SourceFileWindow::accel_activated(int index)
  318. {
  319. if (CURRENT_VIEW && CURRENT_VIEW->hasFocus()) {
  320. switch (index) {
  321. case 0: editUndo(); break;
  322. case 1: editRedo(); break;
  323. case 2: editCut(); break;
  324. case 3: editCopy(); break;
  325. case 4: editPaste(); break;
  326. case 5: // F1 context help
  327. {
  328. int line,col,i;
  329. CURRENT_VIEW->cursorPosition().position(line,col);
  330. QString textLine=CURRENT_VIEW->document()->line(line);
  331. QString wordUnderCursor;
  332. for (i=col-1;i>=0;i--) {
  333. QChar c=textLine[i];
  334. if ((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9')
  335. || c=='_' || c=='$' || c=='#')
  336. wordUnderCursor.prepend(c);
  337. }
  338. int len=textLine.length();
  339. for (i=col;i<len;i++) {
  340. QChar c=textLine[i];
  341. if ((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9')
  342. || c=='_' || c=='$' || c=='#')
  343. wordUnderCursor.append(c);
  344. }
  345. // always open at least the index
  346. force_qt_assistant_page(1);
  347. assistant->openAssistant();
  348. if (wordUnderCursor.isEmpty()) return;
  349. QString docFile=lookup_doc_keyword(wordUnderCursor);
  350. if (docFile.isEmpty()) return;
  351. // wait for Qt Assistant to actually open
  352. while (!assistant->isOpen())
  353. QCoreApplication::processEvents(QEventLoop::ExcludeUserInput,1000);
  354. assistant->showPage(QString(tigcc_base)+QString("/doc/html/")+docFile);
  355. break;
  356. }
  357. case 6:
  358. case 7:
  359. // FIXME: Send ENTER key in some way, or replace newLineHook with a
  360. // better solution altogether.
  361. CURRENT_VIEW->document()->startEditing();
  362. CURRENT_VIEW->removeSelectionText();
  363. CURRENT_VIEW->insertText("\n");
  364. CURRENT_VIEW->document()->endEditing();
  365. current_view_newLineHook();
  366. break;
  367. case 8:
  368. new TemplatePopup(CURRENT_VIEW);
  369. break;
  370. case 9:
  371. case 10:
  372. // Completion only operates on C files.
  373. if (THIS->isCFile) {
  374. // Disable newLineHook.
  375. THIS->accel->setItemEnabled(6,FALSE);
  376. THIS->accel->setItemEnabled(7,FALSE);
  377. new CompletionPopup(CURRENT_VIEW,THIS->fileName,THIS->mainForm,this);
  378. }
  379. break;
  380. default: break;
  381. }
  382. } else if (index == 6 || index == 7) {
  383. QKeyEvent *keyEvent=new QKeyEvent(QEvent::KeyPress,Qt::Key_Return,'\n',0,"\n");
  384. QApplication::postEvent(focusWidget(),keyEvent);
  385. }
  386. }
  387. void SourceFileWindow::completionPopup_closed()
  388. {
  389. // Restore newLineHook.
  390. THIS->accel->setItemEnabled(6,TRUE);
  391. THIS->accel->setItemEnabled(7,TRUE);
  392. }
  393. void *SourceFileWindow::createView(const QString &fileName, const QString &fileText, const QString &hlModeName, unsigned tabWidth)
  394. {
  395. // Create Document object.
  396. KParts::Factory *factory = (KParts::Factory *)
  397. KLibLoader::self()->factory ("libkatepart");
  398. if (!factory) qFatal("Failed to load KatePart");
  399. KTextEditor::Document *doc = (KTextEditor::Document *)
  400. factory->createPart(0,THIS->mainForm,"KTextEditor::Document");
  401. // Set the file name for printing.
  402. doc->setModified(FALSE);
  403. if (doc->openStream("text/plain",fileName))
  404. doc->closeStream();
  405. // Create View object.
  406. KTextEditor::View *newView = (KTextEditor::View *) doc->createView(centralWidget());
  407. newView->hide();
  408. newView->setSizePolicy(QSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored,0,0));
  409. // Set highlighting mode.
  410. KTextEditor::HighlightingInterface *hliface
  411. =qobject_cast<KTextEditor::HighlightingInterface*>(newView->document());
  412. hliface->setHighlighting(hlModeName);
  413. // Set options.
  414. KTextEditor::ConfigInterface *configiface
  415. =qobject_cast<KTextEditor::ConfigInterface*>(newView);
  416. configiface->setConfigValue("dynamic-word-wrap",false);
  417. #if 0 // FIXME: remove spaces, tab width
  418. if (preferences.removeTrailingSpaces)
  419. newView->document()->setConfigFlags(newView->document()->configFlags()|(KTextEditor::Document::cfRemoveSpaces|CF_REMOVE_TRAILING_DYN));
  420. else
  421. newView->document()->setConfigFlags(newView->document()->configFlags()&~(KTextEditor::Document::cfRemoveSpaces|CF_REMOVE_TRAILING_DYN));
  422. newView->setTabWidth(tabWidth);
  423. #endif
  424. connect(newView,SIGNAL(cursorPositionChanged()),this,SLOT(current_view_cursorPositionChanged()));
  425. connect(newView->document(),SIGNAL(textChanged()),this,SLOT(current_view_textChanged()));
  426. connect(newView->document(),SIGNAL(undoChanged()),this,SLOT(current_view_undoChanged()));
  427. connect(newView->document(),SIGNAL(selectionChanged()),this,SLOT(current_view_selectionChanged()));
  428. connect(newView->document(),SIGNAL(charactersInteractivelyInserted(int,int,const QString&)),this,SLOT(current_view_charactersInteractivelyInserted(int,int,const QString&)));
  429. newView->setContextMenu(THIS->te_popup);
  430. // Set text.
  431. SET_TEXT_SAFE(newView->document(),fileText);
  432. newView->document()->setModified(FALSE);
  433. // FIXME
  434. // newView->document()->clearUndo();
  435. // newView->document()->clearRedo();
  436. newView->setCursorPosition(KTextEditor::Cursor(0,0));
  437. return newView;
  438. }
  439. // Returns 1 if the source file should not be closed, 0 if it can be closed.
  440. int SourceFileWindow::savePrompt(void)
  441. {
  442. int result;
  443. if (!CURRENT_VIEW) return 0;
  444. while (CURRENT_VIEW->document()->isModified()) { // "while" in case saving fails!
  445. result=KMessageBox::questionYesNoCancel(this,QString("The file \'%1\' has been modified. Do you want to save the changes?").arg(THIS->fileName),QString::null,KStandardGuiItem::save(),KStandardGuiItem::discard());
  446. if (result==KMessageBox::Yes)
  447. fileSave();
  448. else if (result==KMessageBox::No)
  449. return 0;
  450. else
  451. return 1;
  452. }
  453. return 0;
  454. }
  455. void SourceFileWindow::removeTrailingSpacesFromView(void *view)
  456. {
  457. if (!preferences.removeTrailingSpaces) return;
  458. KTextEditor::View *kateView=reinterpret_cast<KTextEditor::View *>(view);
  459. KTextEditor::Document *doc=kateView->document();
  460. doc->startEditing();
  461. unsigned numLines=doc->lines();
  462. for (unsigned i=0; i<numLines; i++) {
  463. QString line=doc->line(i);
  464. int whitespace=line.find(QRegExp("\\s+$"));
  465. if (whitespace>=0) doc->removeText(KTextEditor::Range(i,whitespace,i,line.length()));
  466. }
  467. doc->endEditing();
  468. }
  469. void SourceFileWindow::fileSave()
  470. {
  471. THIS->dirWatch->removeFile(THIS->fileName);
  472. if (saveFileText(THIS->fileName,CURRENT_VIEW->document()->text())) {
  473. KMessageBox::error(this,QString("Can't save to \'%1\'").arg(THIS->fileName));
  474. THIS->dirWatch->addFile(THIS->fileName);
  475. } else {
  476. THIS->dirWatch->addFile(THIS->fileName);
  477. removeTrailingSpacesFromView(CURRENT_VIEW);
  478. CURRENT_VIEW->document()->setModified(FALSE);
  479. }
  480. }
  481. void SourceFileWindow::fileSaveAs()
  482. {
  483. QString saveFileName=MainForm::SGetFileName(KFileDialog::Saving,
  484. (THIS->fileName.endsWith(".h")?TIGCC_H_Filter TIGCCAllFilter:
  485. THIS->fileName.endsWith(".c")?TIGCC_C_Filter TIGCCAllFilter:
  486. THIS->fileName.endsWith(".s")?TIGCC_S_Filter TIGCCAllFilter:
  487. THIS->fileName.endsWith(".asm")?TIGCC_ASM_Filter TIGCCAllFilter:
  488. THIS->fileName.endsWith(".qll")?TIGCC_QLL_Filter TIGCCAllFilter:
  489. THIS->fileName.endsWith(".txt")?TIGCC_TXT_Filter TIGCCAllFilter:
  490. TIGCCAllFilter),"Save Source File",this);
  491. if (saveFileName.isEmpty())
  492. return;
  493. THIS->dirWatch->removeFile(THIS->fileName);
  494. if (saveFileText(saveFileName,CURRENT_VIEW->document()->text())) {
  495. KMessageBox::error(this,QString("Can't save to \'%1\'").arg(saveFileName));
  496. THIS->dirWatch->addFile(THIS->fileName);
  497. } else {
  498. if (saveFileName.compare(THIS->fileName)) {
  499. // Update the file name for printing.
  500. int line,col;
  501. QString fileText=CURRENT_VIEW->document()->text();
  502. KTextEditor::HighlightingInterface *hliface
  503. =qobject_cast<KTextEditor::HighlightingInterface*>(CURRENT_VIEW->document());
  504. QString hlMode=hliface->highlighting();
  505. CURRENT_VIEW->cursorPosition().position(line,col);
  506. CURRENT_VIEW->document()->setModified(FALSE);
  507. if (CURRENT_VIEW->document()->openStream("text/plain",saveFileName))
  508. CURRENT_VIEW->document()->closeStream();
  509. SET_TEXT_SAFE(CURRENT_VIEW->document(),fileText);
  510. // FIXME
  511. // CURRENT_VIEW->document()->clearUndo();
  512. // CURRENT_VIEW->document()->clearRedo();
  513. hliface->setHighlighting(hlMode);
  514. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(line,col));
  515. // Update the caption
  516. setCaption(caption().left(caption().find('-')+2)+saveFileName);
  517. }
  518. THIS->fileName=saveFileName;
  519. THIS->dirWatch->addFile(saveFileName);
  520. removeTrailingSpacesFromView(CURRENT_VIEW);
  521. CURRENT_VIEW->document()->setModified(FALSE);
  522. updateRightStatusLabel();
  523. }
  524. }
  525. void SourceFileWindow::fileAddToProject()
  526. {
  527. THIS->mainForm->adoptSourceFile(THIS);
  528. }
  529. void SourceFileWindow::fileCompile()
  530. {
  531. THIS->mainForm->compileSourceFile(THIS);
  532. }
  533. void SourceFileWindow::filePrint()
  534. {
  535. if (CURRENT_VIEW) CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Print))->trigger();
  536. }
  537. void SourceFileWindow::filePrintQuickly()
  538. {
  539. // This still shows the print dialog, but then KDE 3.5 Kate did that too
  540. // despite having 2 nominally different APIs (print and printDialog).
  541. if (CURRENT_VIEW) CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Print))->trigger();
  542. }
  543. void SourceFileWindow::applyPreferences()
  544. {
  545. // Apply the KatePart preferences and treeview icons.
  546. KParts::Factory *factory=(KParts::Factory *)
  547. KLibLoader::self()->factory("libkatepart");
  548. if (!factory) qFatal("Failed to load KatePart");
  549. KTextEditor::Document *doc=(KTextEditor::Document *)
  550. factory->createPart(0,this,"KTextEditor::Document");
  551. KTextEditor::Editor *editor=doc->editor();
  552. int numConfigPages=editor->configPages();
  553. for (int i=0; i<numConfigPages; i++) {
  554. if (editor->configPageName(i)=="Fonts & Colors") {
  555. KTextEditor::ConfigPage *configPage=editor->configPage(i,this);
  556. configPage->apply();
  557. delete configPage;
  558. break;
  559. }
  560. }
  561. delete doc;
  562. KTextEditor::View *kateView=CURRENT_VIEW;
  563. if (kateView) {
  564. QString fileText=kateView->document()->text();
  565. #if 0 // FIXME: remove spaces, tab width
  566. if (preferences.removeTrailingSpaces)
  567. kateView->document()->setConfigFlags(kateView->document()->configFlags()|(KTextEditor::Document::cfRemoveSpaces|CF_REMOVE_TRAILING_DYN));
  568. else
  569. kateView->document()->setConfigFlags(kateView->document()->configFlags()&~(KTextEditor::Document::cfRemoveSpaces|CF_REMOVE_TRAILING_DYN));
  570. kateView->setTabWidth(THIS->isASMFile?preferences.tabWidthAsm:
  571. THIS->isCFile?preferences.tabWidthC:8);
  572. #endif
  573. // Kate seems really insisting on making it a pain to update syntax highlighting settings.
  574. KTextEditor::HighlightingInterface *hliface
  575. =qobject_cast<KTextEditor::HighlightingInterface*>(kateView->document());
  576. hliface->setHighlighting(HL_MODE);
  577. // Force redrawing to get the tab width right, repaint() is ignored for some reason.
  578. kateView->hide();
  579. kateView->show();
  580. }
  581. // Apply the icon preferences.
  582. setUsesBigPixmaps(preferences.useSystemIcons);
  583. if (preferences.useSystemIcons) {
  584. fileSaveAction->setIconSet(KIcon("filesave"));
  585. fileAddToProjectAction->setIconSet(KIcon("edit_add"));
  586. fileCompileAction->setIconSet(KIcon("compfile"));
  587. filePrintAction->setIconSet(KIcon("fileprint"));
  588. filePrintQuicklyAction->setIconSet(KIcon("fileprint"));
  589. editClearAction->setIconSet(KIcon("editdelete"));
  590. editCutAction->setIconSet(KIcon("editcut"));
  591. editCopyAction->setIconSet(KIcon("editcopy"));
  592. editPasteAction->setIconSet(KIcon("editpaste"));
  593. findFindAction->setIconSet(KIcon("filefind"));
  594. if (KIconLoader::global()->iconPath("stock-find-and-replace",K3Icon::Small,TRUE).isEmpty())
  595. findReplaceAction->setIconSet(QIcon(qPixmapFromMimeSource("filereplace.png")));
  596. else
  597. findReplaceAction->setIconSet(KIcon("stock-find-and-replace"));
  598. editUndoAction->setIconSet(KIcon("undo"));
  599. editRedoAction->setIconSet(KIcon("redo"));
  600. findFunctionsAction->setIconSet(KIcon("view_tree"));
  601. editIncreaseIndentAction->setIconSet(KIcon("indent"));
  602. editDecreaseIndentAction->setIconSet(KIcon("unindent"));
  603. } else {
  604. fileSaveAction->setIconSet(QIcon(qPixmapFromMimeSource("02")));
  605. fileAddToProjectAction->setIconSet(QIcon(qPixmapFromMimeSource("08")));
  606. fileCompileAction->setIconSet(QIcon(qPixmapFromMimeSource("09")));
  607. filePrintAction->setIconSet(QIcon(qPixmapFromMimeSource("03")));
  608. filePrintQuicklyAction->setIconSet(QIcon(qPixmapFromMimeSource("03")));
  609. editClearAction->setIconSet(QIcon(qPixmapFromMimeSource("04")));
  610. editCutAction->setIconSet(QIcon(qPixmapFromMimeSource("05")));
  611. editCopyAction->setIconSet(QIcon(qPixmapFromMimeSource("06")));
  612. editPasteAction->setIconSet(QIcon(qPixmapFromMimeSource("07")));
  613. findFindAction->setIconSet(QIcon(qPixmapFromMimeSource("13")));
  614. findReplaceAction->setIconSet(QIcon(qPixmapFromMimeSource("14")));
  615. editUndoAction->setIconSet(QIcon(qPixmapFromMimeSource("16")));
  616. editRedoAction->setIconSet(QIcon(qPixmapFromMimeSource("17")));
  617. findFunctionsAction->setIconSet(QIcon(qPixmapFromMimeSource("18")));
  618. editIncreaseIndentAction->setIconSet(QIcon(qPixmapFromMimeSource("19")));
  619. editDecreaseIndentAction->setIconSet(QIcon(qPixmapFromMimeSource("20")));
  620. }
  621. }
  622. void SourceFileWindow::editUndo()
  623. {
  624. if (CURRENT_VIEW)
  625. CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Undo))->trigger();
  626. }
  627. void SourceFileWindow::editRedo()
  628. {
  629. if (CURRENT_VIEW)
  630. CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Redo))->trigger();
  631. }
  632. void SourceFileWindow::editClear()
  633. {
  634. if (CURRENT_VIEW)
  635. CURRENT_VIEW->removeSelectionText();
  636. }
  637. void SourceFileWindow::editCut()
  638. {
  639. if (CURRENT_VIEW)
  640. CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Cut))->trigger();
  641. }
  642. void SourceFileWindow::editCopy()
  643. {
  644. if (CURRENT_VIEW)
  645. CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Copy))->trigger();
  646. }
  647. void SourceFileWindow::editPaste()
  648. {
  649. if (CURRENT_VIEW)
  650. CURRENT_VIEW->action(KStandardAction::name(KStandardAction::PasteText))->trigger();
  651. }
  652. void SourceFileWindow::editSelectAll()
  653. {
  654. if (CURRENT_VIEW)
  655. CURRENT_VIEW->action(KStandardAction::name(KStandardAction::SelectAll))->trigger();
  656. }
  657. void SourceFileWindow::editIncreaseIndent()
  658. {
  659. if (CURRENT_VIEW)
  660. CURRENT_VIEW->action("tools_indent")->trigger();
  661. }
  662. void SourceFileWindow::editDecreaseIndent()
  663. {
  664. if (CURRENT_VIEW)
  665. CURRENT_VIEW->action("tools_unindent")->trigger();
  666. }
  667. void SourceFileWindow::findFind()
  668. {
  669. if (THIS->kfinddialog)
  670. KWin::activateWindow(THIS->kfinddialog->winId());
  671. else {
  672. // Never set hasSelection because finding in selection doesn't really make
  673. // sense with my non-modal find dialog setup.
  674. THIS->kfinddialog=new KFindDialog(false,this,0,KFind::FromCursor,findHistory);
  675. connect(THIS->kfinddialog, SIGNAL(okClicked()), this, SLOT(findFind_next()));
  676. connect(THIS->kfinddialog, SIGNAL(cancelClicked()), this, SLOT(findFind_stop()));
  677. THIS->kfinddialog->show();
  678. }
  679. }
  680. void SourceFileWindow::findFind_next()
  681. {
  682. // Use a local KFind object. The search will need to be restarted next time
  683. // this function is called because of the non-modality of the find dialog.
  684. KFind *kfind=new KFind(THIS->kfinddialog->pattern(),THIS->kfinddialog->options(),this,THIS->kfinddialog);
  685. // Initialize.
  686. bool findBackwards=!!(THIS->kfinddialog->options()&KFind::FindBackwards);
  687. int findCurrentCol;
  688. kfind=new KFind(THIS->kfinddialog->pattern(),THIS->kfinddialog->options(),this,THIS->kfinddialog);
  689. kfind->closeFindNextDialog(); // don't use this, a non-modal KFindDialog is used instead
  690. connect(kfind,SIGNAL(highlight(const QString &,int,int)),
  691. this,SLOT(findFind_highlight(const QString &,int,int)));
  692. if (THIS->kfinddialog->options()&KFind::FromCursor) {
  693. if (CURRENT_VIEW->selection()) {
  694. if (findBackwards) {
  695. THIS->findCurrentLine=CURRENT_VIEW->document()->selStartLine();
  696. findCurrentCol=CURRENT_VIEW->document()->selStartCol()-1;
  697. if (findCurrentCol==-1) {
  698. if (!THIS->findCurrentLine) goto skip_data;
  699. THIS->findCurrentLine--;
  700. }
  701. } else {
  702. THIS->findCurrentLine=CURRENT_VIEW->document()->selEndLine();
  703. findCurrentCol=CURRENT_VIEW->document()->selEndCol();
  704. }
  705. } else {
  706. CURRENT_VIEW->cursorPosition().position(THIS->findCurrentLine,findCurrentCol);
  707. }
  708. } else {
  709. THIS->findCurrentLine=findBackwards?(CURRENT_VIEW->document()->lines()-1):0;
  710. findCurrentCol=-1;
  711. }
  712. kfind->setData(CURRENT_VIEW->document()->line(THIS->findCurrentLine),findCurrentCol);
  713. skip_data:;
  714. // Now find the next occurrence.
  715. KFind::Result result;
  716. KTextEditor::View *currView=CURRENT_VIEW;
  717. int currNumLines=CURRENT_VIEW->document()->lines();
  718. do {
  719. if (kfind->needData()) {
  720. if (findBackwards?!THIS->findCurrentLine:(THIS->findCurrentLine>=currNumLines)) {
  721. // Try restarting the search.
  722. currNumLines=currView->document()->lines();
  723. THIS->findCurrentLine=findBackwards?currNumLines-1:0;
  724. do {
  725. if (kfind->needData()) {
  726. if (findBackwards?!THIS->findCurrentLine:(THIS->findCurrentLine>=currNumLines))
  727. goto not_found_current;
  728. if (findBackwards) THIS->findCurrentLine--; else THIS->findCurrentLine++;
  729. kfind->setData(currView->document()->line(THIS->findCurrentLine));
  730. }
  731. result=kfind->find();
  732. } while (result==KFind::NoMatch);
  733. break;
  734. not_found_current:
  735. KMessageBox::error(this,QString("Text \'%1\' not found").arg(THIS->kfinddialog->pattern()));
  736. delete kfind;
  737. return;
  738. } else if (findBackwards) THIS->findCurrentLine--; else THIS->findCurrentLine++;
  739. kfind->setData(currView->document()->line(THIS->findCurrentLine));
  740. }
  741. result=kfind->find();
  742. } while (result==KFind::NoMatch);
  743. delete kfind;
  744. }
  745. #define unused_text text __attribute__((unused))
  746. void SourceFileWindow::findFind_highlight(const QString &unused_text, int matchingindex, int matchedlength)
  747. {
  748. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(THIS->findCurrentLine,matchingindex+matchedlength));
  749. CURRENT_VIEW->document()->setSelection(THIS->findCurrentLine,matchingindex,
  750. THIS->findCurrentLine,matchingindex+matchedlength);
  751. }
  752. void SourceFileWindow::findFind_stop()
  753. {
  754. if (THIS->kfinddialog) {
  755. findHistory=THIS->kfinddialog->findHistory();
  756. THIS->kfinddialog->deleteLater();
  757. }
  758. THIS->kfinddialog=static_cast<KFindDialog *>(NULL);
  759. }
  760. void SourceFileWindow::findReplace()
  761. {
  762. if (THIS->kreplace) {
  763. KDialogBase *replaceNextDialog=THIS->kreplace->replaceNextDialog();
  764. if (replaceNextDialog)
  765. KWin::activateWindow(replaceNextDialog->winId());
  766. return;
  767. }
  768. KReplaceDialog kreplacedialog(this,0,((CURRENT_VIEW&&CURRENT_VIEW->selection()
  769. &&CURRENT_VIEW->document()->selStartLine()!=CURRENT_VIEW->document()->selEndLine())?
  770. KFind::SelectedText:0)|KFind::FromCursor,
  771. findHistory,replacementHistory,
  772. CURRENT_VIEW&&CURRENT_VIEW->selection());
  773. if (kreplacedialog.exec()!=QDialog::Accepted)
  774. return;
  775. findHistory=kreplacedialog.findHistory();
  776. replacementHistory=kreplacedialog.replacementHistory();
  777. THIS->kreplace=new KReplaceWithSelectionS(kreplacedialog.pattern(),kreplacedialog.replacement(),
  778. kreplacedialog.options(),this);
  779. // Connect signals to code which handles highlighting of found text, and
  780. // on-the-fly replacement.
  781. connect(THIS->kreplace,SIGNAL(highlight(const QString &,int,int)),
  782. this,SLOT(findReplace_highlight(const QString &,int,int)));
  783. // Connect findNext signal - called when pressing the button in the dialog.
  784. connect(THIS->kreplace,SIGNAL(findNext()),this,SLOT(findReplace_next()));
  785. // Connect replace signal - called when doing a replacement.
  786. connect(THIS->kreplace,SIGNAL(replace(const QString &,int,int,int)),
  787. this,SLOT(findReplace_replace(const QString &,int,int,int)));
  788. // Connect dialogClosed signal - called when closing the Replace Next dialog.
  789. connect(THIS->kreplace,SIGNAL(dialogClosed()),this,SLOT(findReplace_stop()));
  790. // Initialize.
  791. bool findBackwards=!!(THIS->kreplace->options()&KFind::FindBackwards);
  792. int replaceCurrentCol;
  793. if (CURRENT_VIEW) {
  794. if (THIS->kreplace->options()&KFind::SelectedText) {
  795. THIS->kreplace->setSelection(CURRENT_VIEW->document()->selStartLine(),
  796. CURRENT_VIEW->document()->selStartCol(),
  797. CURRENT_VIEW->document()->selEndLine(),
  798. CURRENT_VIEW->document()->selEndCol());
  799. if (findBackwards) {
  800. THIS->kreplace->replaceCurrentLine=THIS->kreplace->selEndLine();
  801. replaceCurrentCol=THIS->kreplace->selEndCol();
  802. } else {
  803. THIS->kreplace->replaceCurrentLine=THIS->kreplace->selStartLine();
  804. replaceCurrentCol=THIS->kreplace->selStartCol();
  805. }
  806. THIS->kreplace->setOptions(THIS->kreplace->options()&~KFind::FromCursor);
  807. } else if (THIS->kreplace->options()&KFind::FromCursor) {
  808. if (CURRENT_VIEW->selection()) {
  809. if (findBackwards) {
  810. THIS->kreplace->replaceCurrentLine=CURRENT_VIEW->document()->selStartLine();
  811. replaceCurrentCol=CURRENT_VIEW->document()->selStartCol()-1;
  812. if (replaceCurrentCol==-1) {
  813. if (!THIS->kreplace->replaceCurrentLine) goto skip_data;
  814. THIS->kreplace->replaceCurrentLine--;
  815. }
  816. } else {
  817. THIS->kreplace->replaceCurrentLine=CURRENT_VIEW->document()->selEndLine();
  818. replaceCurrentCol=CURRENT_VIEW->document()->selEndCol();
  819. }
  820. } else {
  821. CURRENT_VIEW->cursorPosition().position(THIS->kreplace->replaceCurrentLine,replaceCurrentCol);
  822. // Don't prompt for restarting if we actually searched the entire document.
  823. if (findBackwards?(THIS->kreplace->replaceCurrentLine==(CURRENT_VIEW->document()->lines()-1)
  824. && replaceCurrentCol==(CURRENT_VIEW->document()->lineLength(THIS->kreplace->replaceCurrentLine)))
  825. :(!THIS->kreplace->replaceCurrentLine&&!replaceCurrentCol))
  826. THIS->kreplace->setOptions(THIS->kreplace->options()&~KFind::FromCursor);
  827. }
  828. } else {
  829. THIS->kreplace->replaceCurrentLine=findBackwards?(CURRENT_VIEW->document()->lines()-1):0;
  830. replaceCurrentCol=-1;
  831. }
  832. THIS->kreplace->setData(CURRENT_VIEW->document()->line(THIS->kreplace->replaceCurrentLine),replaceCurrentCol);
  833. }
  834. skip_data:
  835. // Now find the next occurrence.
  836. findReplace_next(TRUE);
  837. }
  838. void SourceFileWindow::findReplace_next()
  839. {
  840. findReplace_next(FALSE);
  841. }
  842. void SourceFileWindow::findReplace_next(bool firstTime)
  843. {
  844. bool findBackwards=!!(THIS->kreplace->options()&KFind::FindBackwards);
  845. // Reinitialize.
  846. if (!firstTime) {
  847. int replaceCurrentCol;
  848. // Non-first-time always continues from cursor.
  849. if (CURRENT_VIEW->selection()) {
  850. if (findBackwards) {
  851. THIS->kreplace->replaceCurrentLine=CURRENT_VIEW->document()->selStartLine();
  852. replaceCurrentCol=CURRENT_VIEW->document()->selStartCol()-1;
  853. if (replaceCurrentCol==-1) {
  854. if (!THIS->kreplace->replaceCurrentLine) goto skip_data;
  855. THIS->kreplace->replaceCurrentLine--;
  856. }
  857. } else {
  858. THIS->kreplace->replaceCurrentLine=CURRENT_VIEW->document()->selEndLine();
  859. replaceCurrentCol=CURRENT_VIEW->document()->selEndCol();
  860. }
  861. } else {
  862. CURRENT_VIEW->cursorPosition().position(THIS->kreplace->replaceCurrentLine,
  863. replaceCurrentCol);
  864. }
  865. THIS->kreplace->setData(CURRENT_VIEW->document()->line(THIS->kreplace->replaceCurrentLine),replaceCurrentCol);
  866. }
  867. skip_data:;
  868. // Now find the next occurrence.
  869. KFind::Result result;
  870. KTextEditor::View *currView=CURRENT_VIEW;
  871. int currNumLines=0;
  872. if (CURRENT_VIEW) currNumLines=CURRENT_VIEW->document()->lines();
  873. do {
  874. if (THIS->kreplace->needData()) {
  875. if (THIS->kreplace->haveSelection()
  876. ?(findBackwards?(THIS->kreplace->replaceCurrentLine<=THIS->kreplace->selStartLine())
  877. :(THIS->kreplace->replaceCurrentLine>=THIS->kreplace->selEndLine()))
  878. :(findBackwards?!THIS->kreplace->replaceCurrentLine:(THIS->kreplace->replaceCurrentLine>=currNumLines))) {
  879. if (THIS->kreplace->shouldRestart()) {
  880. // Drop "From cursor" and "Selected text" options.
  881. THIS->kreplace->setOptions(THIS->kreplace->options()&~(KFind::FromCursor
  882. |KFind::SelectedText));
  883. THIS->kreplace->invalidateSelection();
  884. // Reinitialize.
  885. THIS->kreplace->replaceCurrentLine=findBackwards?(CURRENT_VIEW->document()->lines()-1):0;
  886. THIS->kreplace->setData(CURRENT_VIEW->document()->line(THIS->kreplace->replaceCurrentLine));
  887. // Start again as if it was the first time.
  888. findReplace_next(TRUE);
  889. return;
  890. } else {
  891. findReplace_stop();
  892. return;
  893. }
  894. } else if (findBackwards) THIS->kreplace->replaceCurrentLine--; else THIS->kreplace->replaceCurrentLine++;
  895. THIS->kreplace->setData(currView->document()->line(THIS->kreplace->replaceCurrentLine));
  896. }
  897. result=THIS->kreplace->replace();
  898. } while (result==KFind::NoMatch);
  899. }
  900. void SourceFileWindow::findReplace_highlight(const QString &unused_text, int matchingindex, int matchedlength)
  901. {
  902. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(THIS->kreplace->replaceCurrentLine,matchingindex+matchedlength));
  903. CURRENT_VIEW->document()->setSelection(THIS->kreplace->replaceCurrentLine,matchingindex,
  904. THIS->kreplace->replaceCurrentLine,matchingindex+matchedlength);
  905. }
  906. void SourceFileWindow::findReplace_replace(const QString &text, int replacementIndex, int replacedLength, int matchedLength)
  907. {
  908. bool update=!!(THIS->kreplace->options()&KReplaceDialog::PromptOnReplace);
  909. bool haveSelection=THIS->kreplace->haveSelection();
  910. // The initializations are redundant, but g++ doesn't understand this, and the
  911. // self-initialization trick doesn't work either (-Wno-init-self is ignored).
  912. int selStartLine=0, selStartCol=0, selEndLine=0, selEndCol=0;
  913. if (haveSelection) {
  914. selStartLine=THIS->kreplace->selStartLine();
  915. selStartCol=THIS->kreplace->selStartCol();
  916. selEndLine=THIS->kreplace->selEndLine();
  917. selEndCol=THIS->kreplace->selEndCol();
  918. }
  919. CURRENT_VIEW->document()->startEditing();
  920. CURRENT_VIEW->document()->insertText(KTextEditor::Cursor(THIS->kreplace->replaceCurrentLine,replacementIndex),
  921. text.mid(replacementIndex,replacedLength));
  922. // We can't put the cursor back now because this breaks editBegin/editEnd.
  923. int line,col;
  924. CURRENT_VIEW->cursorPosition().position(line,col);
  925. bool updateCursor=(line==THIS->kreplace->replaceCurrentLine
  926. && col==replacementIndex+replacedLength);
  927. CURRENT_VIEW->document()->removeText(KTextEditor::Range(THIS->kreplace->replaceCurrentLine,replacementIndex+replacedLength,
  928. THIS->kreplace->replaceCurrentLine,replacementIndex+replacedLength+matchedLength));
  929. CURRENT_VIEW->document()->endEditing();
  930. if (updateCursor)
  931. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(THIS->kreplace->replaceCurrentLine,replacementIndex));
  932. if (update) {
  933. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(THIS->kreplace->replaceCurrentLine,replacementIndex+replacedLength));
  934. CURRENT_VIEW->document()->setSelection(THIS->kreplace->replaceCurrentLine,replacementIndex,
  935. THIS->kreplace->replaceCurrentLine,replacementIndex+replacedLength);
  936. CURRENT_VIEW->repaint();
  937. }
  938. if (haveSelection) {
  939. // Restore selection, updating coordinates if necessary.
  940. THIS->kreplace->setSelection(selStartLine,selStartCol,selEndLine,
  941. (THIS->kreplace->replaceCurrentLine==selEndLine)
  942. ?(selEndCol+replacedLength-matchedLength)
  943. :selEndCol);
  944. }
  945. }
  946. void SourceFileWindow::findReplace_stop()
  947. {
  948. if (THIS->kreplace) THIS->kreplace->deleteLater();
  949. THIS->kreplace=static_cast<KReplaceWithSelectionS *>(NULL);
  950. }
  951. void SourceFileWindow::findFunctions()
  952. {
  953. THIS->functionDialog=new FunctionDialog(this);
  954. connect(THIS->functionDialog->functionListBox,SIGNAL(highlighted(int)),
  955. this,SLOT(findFunctions_functionListBox_highlighted(int)));
  956. connect(THIS->functionDialog->functionListBox,SIGNAL(selected(int)),
  957. this,SLOT(findFunctions_functionListBox_selected(int)));
  958. connect(THIS->functionDialog->prototypeButton,SIGNAL(clicked()),
  959. this,SLOT(findFunctions_prototypeButton_clicked()));
  960. connect(THIS->functionDialog->implementationButton,SIGNAL(clicked()),
  961. this,SLOT(findFunctions_implementationButton_clicked()));
  962. THIS->functionDialog->functionListBox->clear();
  963. THIS->sourceFileFunctions=getFunctions(CURRENT_VIEW->document()->text(),
  964. THIS->isASMFile);
  965. for (SourceFileFunctions::Iterator it=THIS->sourceFileFunctions.begin();
  966. it!=THIS->sourceFileFunctions.end(); ++it)
  967. THIS->functionDialog->functionListBox->insertItem((*it).name);
  968. THIS->functionDialog->exec();
  969. delete THIS->functionDialog;
  970. }
  971. void SourceFileWindow::findFunctions_functionListBox_highlighted(int index)
  972. {
  973. if (index>=0) {
  974. THIS->functionDialog->prototypeButton->setEnabled(
  975. THIS->sourceFileFunctions[index].prototypeLine>=0);
  976. THIS->functionDialog->implementationButton->setEnabled(
  977. THIS->sourceFileFunctions[index].implementationLine>=0);
  978. } else {
  979. THIS->functionDialog->prototypeButton->setEnabled(FALSE);
  980. THIS->functionDialog->implementationButton->setEnabled(FALSE);
  981. }
  982. }
  983. void SourceFileWindow::findFunctions_functionListBox_selected(int index)
  984. {
  985. if (index>=0) {
  986. int line=THIS->sourceFileFunctions[index].implementationLine>=0
  987. ?THIS->sourceFileFunctions[index].implementationLine
  988. :THIS->sourceFileFunctions[index].prototypeLine;
  989. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(line,0));
  990. THIS->functionDialog->accept();
  991. }
  992. }
  993. void SourceFileWindow::findFunctions_prototypeButton_clicked()
  994. {
  995. int index=THIS->functionDialog->functionListBox->currentItem();
  996. if (index>=0 && THIS->sourceFileFunctions[index].prototypeLine>=0) {
  997. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(
  998. THIS->sourceFileFunctions[index].prototypeLine,0));
  999. THIS->functionDialog->accept();
  1000. }
  1001. }
  1002. void SourceFileWindow::findFunctions_implementationButton_clicked()
  1003. {
  1004. int index=THIS->functionDialog->functionListBox->currentItem();
  1005. if (index>=0 && THIS->sourceFileFunctions[index].implementationLine>=0) {
  1006. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(
  1007. THIS->sourceFileFunctions[index].implementationLine,0));
  1008. THIS->functionDialog->accept();
  1009. }
  1010. }
  1011. void SourceFileWindow::findFunctionsPopup_aboutToShow()
  1012. {
  1013. THIS->findFunctionsPopup->clear();
  1014. THIS->sourceFileFunctions=getFunctions(CURRENT_VIEW->document()->text(),
  1015. THIS->isASMFile);
  1016. int idx=0;
  1017. for (SourceFileFunctions::Iterator it=THIS->sourceFileFunctions.begin();
  1018. it!=THIS->sourceFileFunctions.end(); ++it,++idx)
  1019. THIS->findFunctionsPopup->insertItem((*it).name,idx);
  1020. }
  1021. void SourceFileWindow::findFunctionsPopup_aboutToHide()
  1022. {
  1023. QTimer::singleShot(0,this,SLOT(findFunctionsPopup_aboutToHide_async()));
  1024. }
  1025. void SourceFileWindow::findFunctionsPopup_aboutToHide_async()
  1026. {
  1027. THIS->findFunctionsPopup->clear();
  1028. }
  1029. void SourceFileWindow::findFunctionsPopup_activated(int id)
  1030. {
  1031. int line=THIS->sourceFileFunctions[id].implementationLine>=0
  1032. ?THIS->sourceFileFunctions[id].implementationLine
  1033. :THIS->sourceFileFunctions[id].prototypeLine;
  1034. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(line,0));
  1035. }
  1036. void SourceFileWindow::findOpenFileAtCursor()
  1037. {
  1038. int line,col,i;
  1039. CURRENT_VIEW->cursorPosition().position(line,col);
  1040. QString textLine=CURRENT_VIEW->document()->line(line);
  1041. int l=textLine.length();
  1042. bool quotesInLine=textLine.contains("\"");
  1043. QString fileName;
  1044. for (i=col;i>=0;i--) {
  1045. QChar c=textLine[i];
  1046. if (!((quotesInLine && c==' ') || (c>='A' && c<='Z') || (c>='a' && c<='z')
  1047. || (c>='0' && c<='9') || QString("_-./\\:").contains(c)))
  1048. break;
  1049. fileName.prepend(c);
  1050. }
  1051. for (i=col+1;i<l;i++) {
  1052. QChar c=textLine[i];
  1053. if (!((quotesInLine && c==' ') || (c>='A' && c<='Z') || (c>='a' && c<='z')
  1054. || (c>='0' && c<='9') || QString("_-./\\:").contains(c)))
  1055. break;
  1056. fileName.append(c);
  1057. }
  1058. THIS->mainForm->findAndOpenFile(fileName,THIS->category);
  1059. }
  1060. void SourceFileWindow::findFindSymbolDeclaration()
  1061. {
  1062. QString fileText=CURRENT_VIEW->document()->text();
  1063. // "Find symbol declaration" only operates on C files.
  1064. if (THIS->isCFile) {
  1065. QString fileName=THIS->fileName;
  1066. QString symbolFile;
  1067. unsigned symbolLine;
  1068. bool systemHeader;
  1069. int line,col,i;
  1070. CURRENT_VIEW->cursorPosition().position(line,col);
  1071. QString textLine=CURRENT_VIEW->document()->line(line);
  1072. QString wordUnderCursor;
  1073. for (i=col-1;i>=0;i--) {
  1074. QChar c=textLine[i];
  1075. if ((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9')
  1076. || c=='_' || c=='$' || c=='#')
  1077. wordUnderCursor.prepend(c);
  1078. }
  1079. int len=textLine.length();
  1080. for (i=col;i<len;i++) {
  1081. QChar c=textLine[i];
  1082. if ((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9')
  1083. || c=='_' || c=='$' || c=='#')
  1084. wordUnderCursor.append(c);
  1085. }
  1086. if (findSymbolInFile(wordUnderCursor,fileText,fileName,THIS->mainForm,
  1087. symbolFile,symbolLine,systemHeader)
  1088. && !symbolFile.isNull()) {
  1089. if (symbolFile==fileName)
  1090. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(symbolLine,0));
  1091. else {
  1092. THIS->mainForm->openHeader(symbolFile,systemHeader,symbolLine);
  1093. if (!systemHeader)
  1094. KWin::activateWindow(THIS->mainForm->winId());
  1095. }
  1096. }
  1097. }
  1098. }
  1099. void SourceFileWindow::updateSizes()
  1100. {
  1101. int rightStatusSize=size().width();
  1102. THIS->rowStatusLabel->setMaximumWidth(30);
  1103. THIS->colStatusLabel->setMaximumWidth(30);
  1104. THIS->charsStatusLabel->setMaximumWidth(100);
  1105. THIS->rightStatusLabel->setMaximumWidth(rightStatusSize-160>0?rightStatusSize-160:0);
  1106. }
  1107. void SourceFileWindow::resizeEvent(QResizeEvent *event)
  1108. {
  1109. Q3MainWindow::resizeEvent(event);
  1110. if (event->size()==event->oldSize()) return;
  1111. updateSizes();
  1112. }
  1113. void SourceFileWindow::statusBar_messageChanged(const QString & message)
  1114. {
  1115. if (message.isNull())
  1116. // Make sure no labels which should be hidden are shown.
  1117. updateRightStatusLabel();
  1118. }
  1119. void SourceFileWindow::updateRightStatusLabel()
  1120. {
  1121. int rightStatusSize=size().width();
  1122. int line, col;
  1123. CURRENT_VIEW->cursorPosition().position(line,col);
  1124. THIS->rowStatusLabel->setMaximumWidth(30);
  1125. THIS->rowStatusLabel->setText(QString("%1").arg(line+1));
  1126. THIS->colStatusLabel->setMaximumWidth(30);
  1127. THIS->colStatusLabel->setText(QString("%1").arg(col+1));
  1128. THIS->charsStatusLabel->setMaximumWidth(100);
  1129. THIS->charsStatusLabel->setText(QString("%1 Characters").arg(CURRENT_VIEW->document()->text().length()));
  1130. THIS->rightStatusLabel->setMaximumWidth(rightStatusSize-160>0?rightStatusSize-160:0);
  1131. THIS->rightStatusLabel->setText(THIS->fileName);
  1132. }
  1133. void SourceFileWindow::current_view_cursorPositionChanged()
  1134. {
  1135. if (CURRENT_VIEW && !disableViewEvents) {
  1136. int line, col;
  1137. CURRENT_VIEW->cursorPosition().position(line,col);
  1138. THIS->rowStatusLabel->setText(QString("%1").arg(line+1));
  1139. THIS->colStatusLabel->setText(QString("%1").arg(col+1));
  1140. }
  1141. }
  1142. void SourceFileWindow::current_view_textChanged()
  1143. {
  1144. if (disableViewEvents) return;
  1145. if (CURRENT_VIEW) {
  1146. THIS->charsStatusLabel->setText(QString("%1 Characters").arg(CURRENT_VIEW->document()->text().length()));
  1147. if (projectCompletion.contains(THIS->fileName))
  1148. projectCompletion[THIS->fileName].dirty=TRUE;
  1149. if (preferences.deleteOverwrittenErrors) MainForm::deleteOverwrittenErrorsIn(THIS);
  1150. }
  1151. if (THIS->kreplace) THIS->kreplace->invalidateSelection();
  1152. }
  1153. void SourceFileWindow::current_view_undoChanged()
  1154. {
  1155. if (CURRENT_VIEW && !disableViewEvents) {
  1156. editUndoAction->setEnabled(CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Undo))->isEnabled());
  1157. editRedoAction->setEnabled(CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Redo))->isEnabled());
  1158. THIS->accel->setItemEnabled(0,CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Undo))->isEnabled());
  1159. THIS->accel->setItemEnabled(1,CURRENT_VIEW->action(KStandardAction::name(KStandardAction::Redo))->isEnabled());
  1160. }
  1161. }
  1162. void SourceFileWindow::current_view_selectionChanged()
  1163. {
  1164. if (CURRENT_VIEW && !disableViewEvents) {
  1165. editClearAction->setEnabled(CURRENT_VIEW->selection());
  1166. editCutAction->setEnabled(CURRENT_VIEW->selection());
  1167. editCopyAction->setEnabled(CURRENT_VIEW->selection());
  1168. THIS->accel->setItemEnabled(2,CURRENT_VIEW->selection());
  1169. THIS->accel->setItemEnabled(3,CURRENT_VIEW->selection());
  1170. }
  1171. }
  1172. void SourceFileWindow::current_view_charactersInteractivelyInserted(int line, int col, const QString &characters)
  1173. {
  1174. if (CURRENT_VIEW) {
  1175. if (preferences.autoBlocks && characters=="{"
  1176. && col==CURRENT_VIEW->document()->lineLength(line)-1) {
  1177. KTextEditor::Document *doc=CURRENT_VIEW->document();
  1178. QString fileText=doc->text();
  1179. // Only for C files.
  1180. if (THIS->isCFile) {
  1181. QString indent=doc->line(line);
  1182. // Only if the line was all whitespace, otherwise wait for Enter to be
  1183. // pressed (prevents annoying the user while typing a string or something).
  1184. if (indent.contains(QRegExp("^\\s*\\{$"))) {
  1185. indent=indent.remove('{');
  1186. QString cursorLine=indent+"\t";
  1187. doc->startEditing();
  1188. doc->insertLine(line+1,cursorLine);
  1189. doc->insertLine(line+2,indent+"}");
  1190. doc->endEditing();
  1191. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(line+1,cursorLine.length()));
  1192. }
  1193. }
  1194. }
  1195. // Completion only operates on C files.
  1196. if (characters=="(" && THIS->isCFile)
  1197. new ArgHintPopup(CURRENT_VIEW,THIS->fileName,THIS->mainForm);
  1198. }
  1199. }
  1200. void SourceFileWindow::current_view_newLineHook()
  1201. {
  1202. int line,col;
  1203. CURRENT_VIEW->cursorPosition().position(line,col);
  1204. KTextEditor::Document *doc=CURRENT_VIEW->document();
  1205. if (preferences.autoBlocks && line && doc->line(line-1).endsWith("{")) {
  1206. QString fileText=doc->text();
  1207. // Only for C files.
  1208. if (THIS->isCFile) {
  1209. QString indent=doc->line(line-1);
  1210. // Remove everything starting from the first non-whitespace character.
  1211. indent=indent.remove(QRegExp("(?!\\s).*$"));
  1212. QString cursorLine=indent+"\t";
  1213. doc->startEditing();
  1214. doc->removeText(KTextEditor::Range(line,0,line,col));
  1215. doc->insertLine(line,cursorLine);
  1216. doc->insertText(KTextEditor::Cursor(line+1,0),indent+"}");
  1217. doc->endEditing();
  1218. CURRENT_VIEW->setCursorPosition(KTextEditor::Cursor(line,cursorLine.length()));
  1219. }
  1220. }
  1221. }
  1222. void SourceFileWindow::clipboard_dataChanged()
  1223. {
  1224. if (CURRENT_VIEW) {
  1225. editPasteAction->setEnabled(!clipboard->text().isNull());
  1226. THIS->accel->setItemEnabled(4,!clipboard->text().isNull());
  1227. }
  1228. }
  1229. void SourceFileWindow::closeEvent(QCloseEvent *e)
  1230. {
  1231. if (!fileCloseAction->isEnabled() || savePrompt())
  1232. e->ignore();
  1233. else {
  1234. e->accept();
  1235. deleteLater();
  1236. }
  1237. }
  1238. void SourceFileWindow::KDirWatch_dirty(const QString &fileName)
  1239. {
  1240. if (!fileName.compare(THIS->fileName)) {
  1241. if (KMessageBox::questionYesNo(this,
  1242. QString("The file \'%1\' has been changed by another program. "
  1243. "Do you want to reload it?").arg(fileName),"File Changed")
  1244. ==KMessageBox::Yes) {
  1245. QString fileText=loadFileText(fileName);
  1246. if (fileText.isNull()) {
  1247. KMessageBox::error(this,QString("Can't open \'%1\'").arg(fileName));
  1248. return;
  1249. }
  1250. SET_TEXT_SAFE(CURRENT_VIEW->document(),fileText);
  1251. CURRENT_VIEW->document()->setModified(FALSE);
  1252. // FIXME
  1253. // CURRENT_VIEW->document()->clearUndo();
  1254. // CURRENT_VIEW->document()->clearRedo();
  1255. updateRightStatusLabel();
  1256. }
  1257. }
  1258. }
  1259. /*
  1260. * Constructs a SourceFileWindow as a child of 'parent', with the
  1261. * name 'name' and widget flags set to 'f'.
  1262. *
  1263. */
  1264. SourceFileWindow::SourceFileWindow(QWidget* parent, const char* name, Qt::WindowFlags fl)
  1265. : Q3MainWindow(parent, name, fl)
  1266. {
  1267. setupUi(this);
  1268. (void)statusBar();
  1269. }
  1270. /*
  1271. * Destroys the object and frees any allocated resources
  1272. */
  1273. SourceFileWindow::~SourceFileWindow()
  1274. {
  1275. destroy();
  1276. // no need to delete child widgets, Qt does it all for us
  1277. }
  1278. /*
  1279. * Sets the strings of the subwidgets using the current
  1280. * language.
  1281. */
  1282. void SourceFileWindow::languageChange()
  1283. {
  1284. retranslateUi(this);
  1285. }