vlp-27 Made Editor Properties dialog using QtDesigner files.
[vlp.git] / src / edit / editor.cpp
1 #include <unistd.h>
2 #include <QtCore/QTextStream>
3 #include <QtGui/QApplication>
4 #include <QtGui/QMenuBar>
5 #include <QtGui/QFileDialog>
6 #include <QtGui/QColor>
7 #include <QtGui/QPalette>
8 #include <QtGui/QCloseEvent>
9 #include <QtGui/QTextDocument>
10 #include <QtGui/QMainWindow>
11 #include <QtGui/QStatusBar>
12 #include <QtGui/QCheckBox>
13 #include <QtGui/QVBoxLayout>
14
15 #include "editor.h"
16 #include "my_edit.h"
17 #include "editor-properties.h"
18
19 #define TYPENUM 5
20
21 /**
22  * @attention Currently not in use
23  */
24 char *UnitTypes[TYPENUM] = {
25         "CLASS",
26         "PROCEDURE",
27         "FUNCTION",
28         "PROCESS",
29         "COROUTINE"
30 };
31
32 /**
33  * My_Edit constructor. Initializes and sets variables of Multiline editor
34  * widget.
35  * @param parent Parent widget of this widget. If set, this widget becomes a 
36  *               child window inside parent. If not set this widget becomes a
37  *               top level window. Default: NULL
38  */
39 My_Edit::My_Edit(QWidget *parent = NULL)
40         : QTextEdit(parent)
41 {
42 }
43
44 /**
45  * @copydoc QWidget::keyPressEvent(QKeyEvent*)
46  */
47 void My_Edit::keyPressEvent(QKeyEvent *ev)
48 {
49         QTextEdit::keyPressEvent(ev);
50         emit cursorMove();
51 }
52
53 /**
54  * Event invoked on program close.
55  * @copydoc QWidget::closeEvent(QCloseEvent*)
56  */
57 void Editor::closeEvent(QCloseEvent * e) {
58         e->accept();
59 }
60
61 /**
62  * Editor constructor. Initializes and sets variables of Loglan Editor.
63  * @param hdir Home directory of program (specified in configuration file)
64  * @param parent Parent widget of this widget. If set, this widget becomes a 
65  *               child window inside parent. If not set this widget becomes a
66  *               top level window. Default: NULL
67  */
68 Editor::Editor(char *hdir, QWidget * parent)
69         : QMainWindow(parent)
70 {
71         setupUi(this);
72
73         strcpy(HomeDir, hdir);
74         find_text = "";
75         sensitive = FALSE;
76
77         /*    m->insertItem( "&LOGLAN ", loglan );*/
78
79         connect(actionQuit, SIGNAL(triggered()), this, SLOT(close()));
80
81         /* comp->insertItem("Compile ", this, SLOT(cmp()), CTRL + Key_C);*/
82         /* comp->insertItem("Gen ", this, SLOT(gen()), CTRL + Key_G);*/
83         /* comp->insertItem("Compile & Gen ", this, SLOT(comp_all()));*/
84
85         /* loglan->insertItem( "Program structure", this, SLOT(log_prog()));*/
86         /* loglan->insertItem( "Unit structure", this, SLOT(log_unit()));*/
87         
88         connect(e, SIGNAL(cursorMove()), this, SLOT(updateline()));
89         connect(actionUndo, SIGNAL(triggered()), e, SLOT(undo()));
90         connect(actionRedo, SIGNAL(triggered()), e, SLOT(redo()));
91         connect(actionCopy, SIGNAL(triggered()), e, SLOT(copy()));
92         connect(actionPaste, SIGNAL(triggered()), e, SLOT(paste()));
93         connect(actionCut, SIGNAL(triggered()), e, SLOT(cut()));
94         connect(actionClear_all, SIGNAL(triggered()), e, SLOT(clear()));
95
96         compiler_path.sprintf("%s/%s", HomeDir, "compile/logcomp");
97         gen_path.sprintf("%s/%s", HomeDir, "compile/gen");
98         file_path.sprintf("%s", HomeDir);
99
100         position = new QLabel();
101         statusBar()->addPermanentWidget(position);
102 }
103
104 /**
105  * Editor destructor
106  */
107 Editor::~Editor()
108 {
109 }
110
111 /**
112  * Displays line:column position of cursor
113  */
114 void Editor::updateline()
115 {
116         char pom[255];
117         int cx;
118         int cy;
119
120         cx = e->textCursor().blockNumber();
121         cy = e->textCursor().columnNumber();
122         sprintf(pom,"%d:%d ", cx, cy);
123         position->setText(pom);
124 }
125
126 /**
127  * Displays additional window 
128  */
129 void Editor::on_actionOpen_triggered()
130 {
131         QString fn = QFileDialog::getOpenFileName(this, "Load file", file_path, "*.log");
132         if (!fn.isEmpty())
133                 load(fn.toAscii().data());
134 }
135
136 /**
137  * Loads given file content to the editor.
138  * @param fileName Filename of file which will be read.
139  */
140 void Editor::load(const char *fileName)
141 {
142         fname.sprintf("%s", fileName);
143
144         QFile f(fileName);
145         if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
146                 return;
147
148 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
149         e->setAutoUpdate(FALSE);
150 */
151         e->clear();
152
153         QTextStream t(&f);
154         while (!t.atEnd()) {
155                 QString s = t.readLine();
156                 e->append(s);
157         }
158         f.close();
159
160 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
161         e->setAutoUpdate(TRUE);
162 */
163         e->repaint();
164         setWindowTitle(fileName);
165 }
166
167 /**
168  * Saves editor content to the file.
169  * If content has been read from file, it is written to this file. Otherwise
170  * dialog is shown to save content to the specified by user, file.
171  */
172 void Editor::on_actionSave_triggered()
173 {
174         if (fname.isEmpty()) {
175                 QString fn = QFileDialog::getSaveFileName(this, "Save file", 
176                                                         file_path, "*.log");
177                 if (!fn.isEmpty()) {
178                         fname.sprintf("%s", fn.toAscii().data());
179                         save(fn.toAscii().data());
180                 }
181         } else {
182                 save(fname.toAscii().data());
183         }
184         setWindowTitle(fname);
185 }
186
187 /**
188  * Saves editor content to the file.
189  * Forces saving editor content to the new file. Special dialog is shown for
190  * that purpose.
191  */
192 void Editor::on_actionSave_as_triggered()
193 {
194         QString fn = QFileDialog::getSaveFileName(this, "Save file as",
195                                                         file_path, "*.log");
196         if (!fn.isEmpty()) {
197                 fname.sprintf("%s", fn.toAscii().data());
198                 save(fn.toAscii().data());
199         }
200         setWindowTitle(fname);
201 }
202
203 /**
204  * Saves editor content to the given filename.
205  * @param fileName File name of the file where content should be saved.
206  */
207 void Editor::save(const char *fileName)
208 {
209         QFile f(fileName);
210         if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
211                 return;
212         f.reset();
213         f.write(e->toPlainText().toAscii().data(), e->toPlainText().length());
214         f.close();
215 }
216
217 /**
218  * Empties editor content.
219  */
220 void Editor::on_actionNew_triggered()
221 {
222         e->clear();
223         fname.sprintf("%s", "");
224 }
225
226 /**
227  * @attention Currently not in use
228  */
229 //void Editor::print()
230 //{
231 //}
232
233 /**
234  * @attention Currently not in use.
235  * 
236  * Saves and compiles code.
237  */
238 void Editor::on_actionCompile_triggered()
239 {
240         on_actionSave_triggered();
241         compile(COMP_MODE);
242 }
243
244 /**
245  * @attention Currently not in use.
246  * 
247  * Generates program.
248  */
249 void Editor::gen()
250 {
251         compile(GEN_MODE);
252 }
253
254 /**
255  * @attention Currently not in use.
256  * 
257  * Saves, compiles and generates code.
258  */
259 void Editor::comp_all()
260 {
261         on_actionSave_triggered();
262         compile(ALL_MODE);
263 }
264
265 /**
266  * Invokes compiler in the giving mode.
267  * @param mode Mode of compilation. Possible values:
268  *             - COMP_MODE - compilation mode
269  *             - GEN_MODE - program generation mode
270  *             - ALL_MODE - compilation & generation mode.
271  */
272 void Editor::compile(int mode)
273 {
274         char cmd[255];
275 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
276         msg->setAutoUpdate(FALSE);
277 */
278         msg->setReadOnly(FALSE);
279         msg->clear();
280         msg->repaint();
281
282         /*i = fname.find('.');*/
283         /* if (i>=0) {*/
284
285         /*  fn.truncate(i);*/
286         switch(mode) {
287         case COMP_MODE:
288                 sprintf(cmd, "%s %s > comp_data!", compiler_path.toAscii().data(),
289                                                         fname.toAscii().data());
290                 break;
291         case GEN_MODE:
292                 sprintf(cmd, "%s %s > comp_data!", gen_path.toAscii().data(),
293                                                         fname.toAscii().data());
294                 break;
295         case ALL_MODE:
296                 sprintf(cmd, "%s %s > comp_data!", compiler_path.toAscii().data(),
297                                                         fname.toAscii().data());
298                 system(cmd);
299                 sprintf(cmd, "%s %s >> comp_data!", gen_path.toAscii().data(),
300                                                         fname.toAscii().data());
301         break;
302         }
303
304         system(cmd);
305         QFile f("comp_data!");
306         if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
307                 return;
308
309         QTextStream t(&f);
310         while (!t.atEnd()) {
311                 QString s = t.readLine();
312                 msg->append(s);
313         }
314         f.close();
315
316         msg->setReadOnly(TRUE);
317
318 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
319         msg->setAutoUpdate(TRUE);
320 */
321         msg->repaint();
322         unlink("comp_data!");
323         /*}*/
324 }
325
326 /**
327  * Displays window with editor properties
328  */
329 void Editor::on_actionProperties_triggered()
330 {
331         EditorProperties *dlg = new EditorProperties(this, Qt::Dialog);
332
333         dlg->setDefaultCompilerPath(compiler_path);
334         dlg->setDefaultFilesPath(file_path);
335         /*
336         tmpQLabel = new QLabel(&dlg, "Label_3");
337         tmpQLabel->setGeometry(10, 100, 100, 30);
338         tmpQLabel->setText("Path to gen:");
339         tmpQLabel->setAlignment(289);
340         tmpQLabel->setMargin(-1);
341         */
342
343         /*
344         QLineEdit* genp;
345         genp = new QLineEdit(&dlg, "g_path");
346         genp->setGeometry(130, 100, 250, 30);
347         genp->setText(gen_path.data());
348         genp->setMaxLength(32767);
349         genp->setEchoMode(QLineEdit::Normal);
350         genp->setFrame(TRUE);
351         */
352
353         if (dlg->exec()) {
354                 compiler_path.sprintf("%s", dlg->getCompilerPath().toAscii().data());
355                 /* gen_path.sprintf("%s",genp->text()); */
356                 file_path.sprintf("%s", dlg->getFilesPath().toAscii().data());
357         };
358 }
359
360 /**
361  * @attention Currently not in use
362  */
363 void Editor::log_unit()
364 {
365         /*
366         Code commented during Qt4 migration.
367         Code is not used, so there is no rush with this...
368         */
369         /*
370         QString txt;
371         QDialog dlg(this, Qt::Dialog);
372         int cx, cy, i;
373         char uname[255];
374
375         QLineEdit* files;
376         files = new QLineEdit(&dlg, "f_path");
377         files->setGeometry(130, 20, 250, 30);
378         files->setText("");
379         files->setMaxLength(32767);
380         files->setEchoMode(QLineEdit::Normal);
381         files->setFrame(TRUE);
382
383         QLabel* tmpQLabel;
384         tmpQLabel = new QLabel(&dlg, "Label_1");
385         tmpQLabel->setGeometry(10, 20, 100, 30);
386         tmpQLabel->setText("Unit name:");
387         tmpQLabel->setAlignment(289);
388         tmpQLabel->setMargin(-1);
389
390         QPushButton* tmpQPushButton;
391         tmpQPushButton = new QPushButton(&dlg, "OkBtn");
392         tmpQPushButton->setGeometry(40, 170, 70, 30);
393         tmpQPushButton->setText("Ok");
394         tmpQPushButton->setAutoRepeat(FALSE);
395         tmpQPushButton->setAutoResize(FALSE);
396         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(accept()));
397
398         tmpQPushButton = new QPushButton(&dlg, "CancelBtn");
399         tmpQPushButton->setGeometry(130, 170, 100, 30);
400         tmpQPushButton->setText("Cancel");
401         tmpQPushButton->setAutoRepeat(FALSE);
402         tmpQPushButton->setAutoResize(FALSE);
403         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(reject()));
404
405         tmpQLabel = new QLabel(&dlg, "Label_1");
406         tmpQLabel->setGeometry(10, 50, 100, 60);
407         tmpQLabel->setText("Unit type:");
408
409         QListBox lst(&dlg, "type");
410         for(i = 0; i < TYPENUM; i++) {
411                 lst.insertItem(UnitTypes[i]);
412         }
413         lst.setGeometry(130, 60, 180, 80);
414         lst.setCurrentItem(0);
415
416         if (dlg.exec()) {
417                 strcpy(uname, files->text());
418                 e->getCursorPosition(&cx, &cy);
419
420                 txt.sprintf("UNIT %s : %s( <params> );\nBEGIN\n\nEND %s;",
421                         uname, lst.text(lst.currentItem()).ascii(), uname);
422                 e->insertAt(txt, cx, cy);
423         }
424         */
425 }
426
427 /**
428  * @attention Currently not in use
429  */
430 void Editor::log_prog()
431 {
432         /*
433         Code commented during Qt4 migration.
434         Code is not used, so there is no rush with this...
435         */
436         /*
437         QString txt;
438         QDialog dlg(this, "unit", TRUE);
439         int cx, cy;
440         char uname[255];
441
442         QLineEdit *files;
443         files = new QLineEdit(&dlg, "f_path");
444         files->setGeometry(130, 20, 250, 30);
445         files->setText("");
446         files->setMaxLength(32767);
447         files->setEchoMode(QLineEdit::Normal);
448         files->setFrame(TRUE);
449
450         QLabel *tmpQLabel;
451         tmpQLabel = new QLabel(&dlg, "Label_1");
452         tmpQLabel->setGeometry(10, 20, 100, 30);
453         tmpQLabel->setText("Program name:");
454
455         QPushButton* tmpQPushButton;
456         tmpQPushButton = new QPushButton(&dlg, "OkBtn");
457         tmpQPushButton->setGeometry(40, 70, 70, 30);
458         tmpQPushButton->setText("Ok");
459         tmpQPushButton->setAutoRepeat(FALSE);
460         tmpQPushButton->setAutoResize(FALSE);
461         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(accept()));
462
463         tmpQPushButton = new QPushButton(&dlg, "CancelBtn");
464         tmpQPushButton->setGeometry(130, 70, 100, 30);
465         tmpQPushButton->setText("Cancel");
466         tmpQPushButton->setAutoRepeat(FALSE);
467         tmpQPushButton->setAutoResize(FALSE);
468         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(reject()));
469
470         if (dlg.exec()) {
471                 strcpy(uname, files->text());
472                 e->getCursorPosition(&cx, &cy);
473
474                 txt.sprintf("PROGRAM %s\n\nBEGIN\n\nEND ", uname);
475                 e->insertAt(txt, cx, cy);
476         }
477         */
478 }
479
480 /**
481  * Searches for given text in editor content.
482  * Displays window to set search parameters. If text is found sets cursor
483  * position on it.
484  */
485 void Editor::on_actionFind_triggered()
486 {
487         QDialog dlg(this, Qt::Dialog);
488         QString *txt;
489         int res, line, pom;
490
491         QLineEdit *tmpQLineEdit;
492         tmpQLineEdit = new QLineEdit("", &dlg);
493         tmpQLineEdit->setGeometry(60, 10, 180, 30);
494
495         QLabel *tmpQLabel;
496         tmpQLabel = new QLabel(&dlg);
497         tmpQLabel->setGeometry(10, 10, 50, 30);
498
499         tmpQLabel->setText("Text:");
500
501         QCheckBox *tmpQRadioButton;
502         tmpQRadioButton = new QCheckBox("Case sensitive", &dlg);
503         tmpQRadioButton->setGeometry(70, 50, 150, 30);
504         tmpQRadioButton->setAutoRepeat(FALSE);
505
506 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
507         tmpQRadioButton->setAutoResize(FALSE);
508 */
509
510         QPushButton *okbtn, *cbtn;
511         okbtn = new QPushButton("Find", &dlg);
512         okbtn->setGeometry(260, 10, 100, 30);
513         okbtn->setDefault(TRUE);
514         connect(okbtn,SIGNAL(clicked()), &dlg, SLOT(accept()));
515
516         cbtn = new QPushButton("Close", &dlg);
517         cbtn->setGeometry(260, 50, 100, 30);
518         connect(cbtn, SIGNAL(clicked()), &dlg, SLOT(reject()));
519         dlg.resize(380, 90);
520
521         if (dlg.exec()) {
522                 sensitive = tmpQRadioButton->isChecked();
523                 find_text = tmpQLineEdit->text();
524                 
525                 QTextDocument::FindFlags flags = 0;
526                 
527                 if (sensitive) {
528                         flags |= QTextDocument::FindCaseSensitively;
529                 }
530                 e->find(find_text, flags);
531         }
532 }
533
534 /**
535  * Searches for next occurence of given text in editor content.
536  * Displays window to set search parameters. If text is found sets cursor
537  * position on it.
538  */
539 void Editor::on_actionFind_next_triggered()
540 {
541         if (!find_text.isEmpty()) {
542                 QTextDocument::FindFlags flags = 0;
543                 
544                 if (sensitive) {
545                         flags |= QTextDocument::FindCaseSensitively;
546                 }
547                 e->find(find_text, flags);
548         }
549 }
550
551 /**
552  * Program main function.
553  * argv[1] is mandatory and should be a path to the home directory of
554  * application (same as in configuration file).
555  * @param argc Number of program arguments
556  * @param argv Program arguments
557  */
558 int main(int argc, char **argv)
559 {
560         QApplication app(argc, argv);
561
562         Editor editor(argv[1], NULL);
563         editor.show();
564
565         return app.exec();
566 }
567