Prepare layout code generation for editor
[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
17 #define TYPENUM 5
18
19 Editor *editor;
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  * @param name @deprecated If set, name is sent to the Qobject constructor, so widget is
39  *             identifiable (e.g. in Qt Designer)
40  */
41 My_Edit::My_Edit(QWidget *parent, const char *name)
42         : QTextEdit(parent)
43 {
44         parent = NULL;
45         name = NULL;
46 }
47
48 /**
49  * @copydoc QWidget::keyPressEvent(QKeyEvent*)
50  */
51 void My_Edit::keyPressEvent(QKeyEvent *ev)
52 {
53         QTextEdit::keyPressEvent(ev);
54         emit cursorMove();
55 }
56
57 /**
58  * Event invoked on program close.
59  * @copydoc QWidget::closeEvent(QCloseEvent*)
60  */
61 void Editor::closeEvent(QCloseEvent * e) {
62         e->accept();
63 }
64
65 /**
66  * Editor constructor. Initializes and sets variables of Loglan Editor.
67  * @param hdir Home directory of program (specified in configuration file)
68  * @param parent Parent widget of this widget. If set, this widget becomes a 
69  *               child window inside parent. If not set this widget becomes a
70  *               top level window. Default: NULL
71  * @param name If set, name is sent to the Qobject constructor, so widget is
72  *             identifiable (e.g. in Qt Designer)
73  */
74 Editor::Editor(char *hdir, QWidget * parent)
75         : QMainWindow(parent)
76 {
77         setupUi(this);
78
79         strcpy(HomeDir, hdir);
80         find_text = "";
81         sensitive = FALSE;
82 //      QMenu * file = NULL;
83 // /*   QMenu * comp = new QMenu();*/
84 // /*   QMenu * loglan = new QMenu();*/
85 //      QMenu * medit = NULL;
86 //      QAction* action = NULL;
87 // 
88 //      file = menuBar()->addMenu("&File");
89 //      medit = menuBar()->addMenu("&Edit");
90 // 
91 //      action = menuBar()->addAction("&Compile", this, SLOT(cmp()));
92 // 
93 //      /*    m->insertItem( "&LOGLAN ", loglan );*/
94 // 
95 //      action = menuBar()->addAction("&Properties", this, SLOT(props()));
96 // 
97 //      file->addAction("New", this, SLOT(create()), QKeySequence(Qt::CTRL + Qt::Key_N));
98 //      file->addAction("Open", this, SLOT(load()), QKeySequence(Qt::CTRL + Qt::Key_O));
99 //      file->addAction("Save", this, SLOT(save()), QKeySequence(Qt::CTRL + Qt::Key_S));
100 //      file->addAction("Save as", this, SLOT(save_as()), QKeySequence(Qt::CTRL + Qt::Key_A));
101 //      file->addSeparator();
102 //      file->addAction("Quit ", this, SLOT(close()));
103
104         /* comp->insertItem("Compile ", this, SLOT(cmp()), CTRL + Key_C);*/
105         /* comp->insertItem("Gen ", this, SLOT(gen()), CTRL + Key_G);*/
106         /* comp->insertItem("Compile & Gen ", this, SLOT(comp_all()));*/
107
108         /* loglan->insertItem( "Program structure", this, SLOT(log_prog()));*/
109         /* loglan->insertItem( "Unit structure", this, SLOT(log_unit()));*/
110
111 //      e = new My_Edit(this, "editor");
112 //      connect(e, SIGNAL(cursorMove()), this, SLOT(updateline()));
113 //      medit->addAction("Copy", e, SLOT(copy()), QKeySequence(Qt::CTRL + Qt::Key_Insert));
114 //      medit->addAction("Paste", e, SLOT(paste()), QKeySequence(Qt::SHIFT + Qt::Key_Insert));
115 //      medit->addAction("Cut", e, SLOT(cut()), QKeySequence(Qt::CTRL + Qt::Key_Delete));
116 //      medit->addAction("Clear All", e, SLOT(clear()));
117 //      medit->addSeparator();
118 //      medit->addAction("Find", this, SLOT(findText()), QKeySequence(Qt::CTRL + Qt::Key_F));
119 //      medit->addAction("Find Next", this, SLOT(find_next()), QKeySequence(Qt::CTRL + Qt::Key_L));
120
121 //      msg = new QTextEdit(this);
122 //      msg->setReadOnly(TRUE);
123 // 
124 //      QVBoxLayout * layout = new QVBoxLayout();
125 //      layout->setContentsMargins (3, 0, 3, 0);
126 //      layout->addWidget(e);
127 //      layout->addWidget(msg);
128 //      QWidget *window = new QWidget();
129 //      window->setLayout(layout);
130 //      setCentralWidget(window);
131
132         compiler_path.sprintf("%s/%s", HomeDir, "compile/logcomp");
133         gen_path.sprintf("%s/%s", HomeDir, "compile/gen");
134         file_path.sprintf("%s", HomeDir);
135
136 //      QColor col(200, 200, 200);
137 //      QPalette grp(Qt::black, col, col.lighter(), col.darker(), col.darker(), Qt::black, col);
138 // 
139 //      msg->setPalette(grp);
140 // 
141 //      position = new QLabel();
142 //      statusBar()->addPermanentWidget(position);
143 }
144
145 /**
146  * Editor destructor
147  */
148 Editor::~Editor()
149 {
150 }
151
152 /**
153  * Displays line:column position of cursor
154  */
155 void Editor::updateline()
156 {
157         char pom[255];
158         int cx;
159         int cy;
160
161         cx = e->textCursor().blockNumber();
162         cy = e->textCursor().columnNumber();
163         sprintf(pom,"%d:%d ", cx, cy);
164         position->setText(pom);
165 }
166
167 /**
168  * Event invoked on resizing editor application window.
169  * @copydoc QWidget::resizeEvent(QResizeEvent*)
170  * @param event Currently does nothing
171  */
172 void Editor::resizeEvent(QResizeEvent *event)
173 {
174 /*
175 TODO: Remove entire method?
176         if (e && m) {
177                 e->setGeometry(0, m->height(), width(),
178                                 3 * (int)((height() - m->height()) / 4));
179
180                 msg->setGeometry(0, m->height() + e->height(), width(),
181                                 (int)((height() - m->height()) / 4));
182
183                 position->setGeometry(width() - 80,
184                                                 m->height() + e->height() - 10,
185                                                 position->width(),
186                                                 position->height());
187         }
188 */
189 }
190
191 /**
192  * Displays additional window 
193  */
194 void Editor::load()
195 {
196         QString fn = QFileDialog::getOpenFileName(this, "Load file", file_path, "*.log");
197         if (!fn.isEmpty())
198                 load(fn.toAscii().data());
199 }
200
201 /**
202  * Loads given file content to the editor.
203  * @param fileName Filename of file which will be read.
204  */
205 void Editor::load(const char *fileName)
206 {
207         fname.sprintf("%s", fileName);
208
209         QFile f(fileName);
210         if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
211                 return;
212
213 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
214         e->setAutoUpdate(FALSE);
215 */
216         e->clear();
217
218         QTextStream t(&f);
219         while (!t.atEnd()) {
220                 QString s = t.readLine();
221                 e->append(s);
222         }
223         f.close();
224
225 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
226         e->setAutoUpdate(TRUE);
227 */
228         e->repaint();
229         setWindowTitle(fileName);
230 }
231
232 /**
233  * Saves editor content to the file.
234  * If content has been read from file, it is written to this file. Otherwise
235  * dialog is shown to save content to the specified by user, file.
236  */
237 void Editor::save()
238 {
239         if (fname.isEmpty()) {
240                 QString fn = QFileDialog::getSaveFileName(this, "Save file", 
241                                                         file_path, "*.log");
242                 if (!fn.isEmpty()) {
243                         fname.sprintf("%s", fn.toAscii().data());
244                         save(fn.toAscii().data());
245                 }
246         } else {
247                 save(fname.toAscii().data());
248         }
249         setWindowTitle(fname);
250 }
251
252 /**
253  * Saves editor content to the file.
254  * Forces saving editor content to the new file. Special dialog is shown for
255  * that purpose.
256  */
257 void Editor::save_as()
258 {
259         QString fn = QFileDialog::getSaveFileName(this, "Save file as",
260                                                         file_path, "*.log");
261         if (!fn.isEmpty()) {
262                 fname.sprintf("%s", fn.toAscii().data());
263                 save(fn.toAscii().data());
264         }
265         setWindowTitle(fname);
266 }
267
268 /**
269  * Saves editor content to the given filename.
270  * @param fileName File name of the file where content should be saved.
271  */
272 void Editor::save(const char *fileName)
273 {
274         QFile f(fileName);
275         if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
276                 return;
277         f.reset();
278         f.write(e->toPlainText().toAscii().data(), e->toPlainText().length());
279         f.close();
280 }
281
282 /**
283  * Empties editor content.
284  */
285 void Editor::create()
286 {
287         e->clear();
288         fname.sprintf("%s", "");
289 }
290
291 /**
292  * @attention Currently not in use
293  */
294 void Editor::print()
295 {
296 }
297
298 /**
299  * @attention Currently not in use.
300  * 
301  * Saves and compiles code.
302  */
303 void Editor::cmp()
304 {
305         save();
306         compile(COMP_MODE);
307 }
308
309 /**
310  * @attention Currently not in use.
311  * 
312  * Generates program.
313  */
314 void Editor::gen()
315 {
316         compile(GEN_MODE);
317 }
318
319 /**
320  * @attention Currently not in use.
321  * 
322  * Saves, compiles and generates code.
323  */
324 void Editor::comp_all()
325 {
326         save();
327         compile(ALL_MODE);
328 }
329
330 /**
331  * Invokes compiler in the giving mode.
332  * @param mode Mode of compilation. Possible values:
333  *             - COMP_MODE - compilation mode
334  *             - GEN_MODE - program generation mode
335  *             - ALL_MODE - compilation & generation mode.
336  */
337 void Editor::compile(int mode)
338 {
339         char cmd[255];
340 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
341         msg->setAutoUpdate(FALSE);
342 */
343         msg->setReadOnly(FALSE);
344         msg->clear();
345         msg->repaint();
346
347         /*i = fname.find('.');*/
348         /* if (i>=0) {*/
349
350         /*  fn.truncate(i);*/
351         switch(mode) {
352         case COMP_MODE:
353                 sprintf(cmd, "%s %s > comp_data!", compiler_path.toAscii().data(),
354                                                         fname.toAscii().data());
355                 break;
356         case GEN_MODE:
357                 sprintf(cmd, "%s %s > comp_data!", gen_path.toAscii().data(),
358                                                         fname.toAscii().data());
359                 break;
360         case ALL_MODE:
361                 sprintf(cmd, "%s %s > comp_data!", compiler_path.toAscii().data(),
362                                                         fname.toAscii().data());
363                 system(cmd);
364                 sprintf(cmd, "%s %s >> comp_data!", gen_path.toAscii().data(),
365                                                         fname.toAscii().data());
366         break;
367         }
368
369         system(cmd);
370         QFile f("comp_data!");
371         if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
372                 return;
373
374         QTextStream t(&f);
375         while (!t.atEnd()) {
376                 QString s = t.readLine();
377                 msg->append(s);
378         }
379         f.close();
380
381         msg->setReadOnly(TRUE);
382
383 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
384         msg->setAutoUpdate(TRUE);
385 */
386         msg->repaint();
387         unlink("comp_data!");
388         /*}*/
389 }
390
391 /**
392  * Displays window with editor properties
393  */
394 void Editor::props()
395 {
396         QDialog dlg(this, Qt::Dialog);
397
398         QLineEdit *files;
399         files = new QLineEdit(&dlg);
400         files->setGeometry(130, 20, 250, 30);
401         files->setText(file_path);
402         files->setMaxLength(32767);
403         files->setEchoMode(QLineEdit::Normal);
404         files->setFrame(TRUE);
405
406         QLabel *tmpQLabel;
407         tmpQLabel = new QLabel("Path to files:", &dlg);
408         tmpQLabel->setGeometry(10, 20, 100, 30);
409         tmpQLabel->setAlignment(Qt::AlignLeft);
410         tmpQLabel->setMargin(-1);
411
412         tmpQLabel = new QLabel("Path to compiler:", &dlg);
413         tmpQLabel->setGeometry(10, 60, 100, 30);
414         tmpQLabel->setAlignment(Qt::AlignLeft);
415         tmpQLabel->setMargin(-1);
416
417         /*
418         tmpQLabel = new QLabel(&dlg, "Label_3");
419         tmpQLabel->setGeometry(10, 100, 100, 30);
420         tmpQLabel->setText("Path to gen:");
421         tmpQLabel->setAlignment(289);
422         tmpQLabel->setMargin(-1);
423         */
424
425         QLineEdit *compp;
426         compp = new QLineEdit(compiler_path, &dlg);
427         compp->setGeometry(130, 60, 250, 30);
428         compp->setMaxLength(32767);
429         compp->setEchoMode(QLineEdit::Normal);
430         compp->setFrame(TRUE);
431
432         /*
433         QLineEdit* genp;
434         genp = new QLineEdit(&dlg, "g_path");
435         genp->setGeometry(130, 100, 250, 30);
436         genp->setText(gen_path.data());
437         genp->setMaxLength(32767);
438         genp->setEchoMode(QLineEdit::Normal);
439         genp->setFrame(TRUE);
440         */
441
442         QPushButton* tmpQPushButton;
443         tmpQPushButton = new QPushButton("Ok", &dlg);
444         tmpQPushButton->setGeometry(90, 100, 70, 30);
445         tmpQPushButton->setAutoRepeat(FALSE);
446 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
447         tmpQPushButton->setAutoResize(FALSE);
448 */
449         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(accept()));
450
451         tmpQPushButton = new QPushButton("Cancel", &dlg);
452         tmpQPushButton->setGeometry(180, 100, 70, 30);
453         tmpQPushButton->setAutoRepeat(FALSE);
454 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
455         tmpQPushButton->setAutoResize(FALSE);
456 */
457         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(reject()));
458         dlg.resize(400, 140);
459
460         if (dlg.exec()) {
461                 compiler_path.sprintf("%s", compp->text().toAscii().data());
462                 /* gen_path.sprintf("%s",genp->text()); */
463                 file_path.sprintf("%s", files->text().toAscii().data());
464         };
465 }
466
467 /**
468  * @attention Currently not in use
469  */
470 void Editor::log_unit()
471 {
472         /*
473         Code commented during Qt4 migration.
474         Code is not used, so there is no rush with this...
475         */
476         /*
477         QString txt;
478         QDialog dlg(this, Qt::Dialog);
479         int cx, cy, i;
480         char uname[255];
481
482         QLineEdit* files;
483         files = new QLineEdit(&dlg, "f_path");
484         files->setGeometry(130, 20, 250, 30);
485         files->setText("");
486         files->setMaxLength(32767);
487         files->setEchoMode(QLineEdit::Normal);
488         files->setFrame(TRUE);
489
490         QLabel* tmpQLabel;
491         tmpQLabel = new QLabel(&dlg, "Label_1");
492         tmpQLabel->setGeometry(10, 20, 100, 30);
493         tmpQLabel->setText("Unit name:");
494         tmpQLabel->setAlignment(289);
495         tmpQLabel->setMargin(-1);
496
497         QPushButton* tmpQPushButton;
498         tmpQPushButton = new QPushButton(&dlg, "OkBtn");
499         tmpQPushButton->setGeometry(40, 170, 70, 30);
500         tmpQPushButton->setText("Ok");
501         tmpQPushButton->setAutoRepeat(FALSE);
502         tmpQPushButton->setAutoResize(FALSE);
503         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(accept()));
504
505         tmpQPushButton = new QPushButton(&dlg, "CancelBtn");
506         tmpQPushButton->setGeometry(130, 170, 100, 30);
507         tmpQPushButton->setText("Cancel");
508         tmpQPushButton->setAutoRepeat(FALSE);
509         tmpQPushButton->setAutoResize(FALSE);
510         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(reject()));
511
512         tmpQLabel = new QLabel(&dlg, "Label_1");
513         tmpQLabel->setGeometry(10, 50, 100, 60);
514         tmpQLabel->setText("Unit type:");
515
516         QListBox lst(&dlg, "type");
517         for(i = 0; i < TYPENUM; i++) {
518                 lst.insertItem(UnitTypes[i]);
519         }
520         lst.setGeometry(130, 60, 180, 80);
521         lst.setCurrentItem(0);
522
523         if (dlg.exec()) {
524                 strcpy(uname, files->text());
525                 e->getCursorPosition(&cx, &cy);
526
527                 txt.sprintf("UNIT %s : %s( <params> );\nBEGIN\n\nEND %s;",
528                         uname, lst.text(lst.currentItem()).ascii(), uname);
529                 e->insertAt(txt, cx, cy);
530         }
531         */
532 }
533
534 /**
535  * @attention Currently not in use
536  */
537 void Editor::log_prog()
538 {
539         /*
540         Code commented during Qt4 migration.
541         Code is not used, so there is no rush with this...
542         */
543         /*
544         QString txt;
545         QDialog dlg(this, "unit", TRUE);
546         int cx, cy;
547         char uname[255];
548
549         QLineEdit *files;
550         files = new QLineEdit(&dlg, "f_path");
551         files->setGeometry(130, 20, 250, 30);
552         files->setText("");
553         files->setMaxLength(32767);
554         files->setEchoMode(QLineEdit::Normal);
555         files->setFrame(TRUE);
556
557         QLabel *tmpQLabel;
558         tmpQLabel = new QLabel(&dlg, "Label_1");
559         tmpQLabel->setGeometry(10, 20, 100, 30);
560         tmpQLabel->setText("Program name:");
561
562         QPushButton* tmpQPushButton;
563         tmpQPushButton = new QPushButton(&dlg, "OkBtn");
564         tmpQPushButton->setGeometry(40, 70, 70, 30);
565         tmpQPushButton->setText("Ok");
566         tmpQPushButton->setAutoRepeat(FALSE);
567         tmpQPushButton->setAutoResize(FALSE);
568         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(accept()));
569
570         tmpQPushButton = new QPushButton(&dlg, "CancelBtn");
571         tmpQPushButton->setGeometry(130, 70, 100, 30);
572         tmpQPushButton->setText("Cancel");
573         tmpQPushButton->setAutoRepeat(FALSE);
574         tmpQPushButton->setAutoResize(FALSE);
575         connect(tmpQPushButton,SIGNAL(clicked()), &dlg, SLOT(reject()));
576
577         if (dlg.exec()) {
578                 strcpy(uname, files->text());
579                 e->getCursorPosition(&cx, &cy);
580
581                 txt.sprintf("PROGRAM %s\n\nBEGIN\n\nEND ", uname);
582                 e->insertAt(txt, cx, cy);
583         }
584         */
585 }
586
587 /**
588  * Searches for given text in editor content.
589  * Displays window to set search parameters. If text is found sets cursor
590  * position on it.
591  */
592 void Editor::findText()
593 {
594         QDialog dlg(this, Qt::Dialog);
595         QString *txt;
596         int res, line, pom;
597
598         QLineEdit *tmpQLineEdit;
599         tmpQLineEdit = new QLineEdit("", &dlg);
600         tmpQLineEdit->setGeometry(60, 10, 180, 30);
601
602         QLabel *tmpQLabel;
603         tmpQLabel = new QLabel(&dlg);
604         tmpQLabel->setGeometry(10, 10, 50, 30);
605
606         tmpQLabel->setText("Text:");
607
608         QCheckBox *tmpQRadioButton;
609         tmpQRadioButton = new QCheckBox("Case sensitive", &dlg);
610         tmpQRadioButton->setGeometry(70, 50, 150, 30);
611         tmpQRadioButton->setAutoRepeat(FALSE);
612
613 /*TODO: Does not exists in Qt4. Use layout and set the size policy (https://qt-project.org/forums/viewthread/2112)
614         tmpQRadioButton->setAutoResize(FALSE);
615 */
616
617         QPushButton *okbtn, *cbtn;
618         okbtn = new QPushButton("Find", &dlg);
619         okbtn->setGeometry(260, 10, 100, 30);
620         okbtn->setDefault(TRUE);
621         connect(okbtn,SIGNAL(clicked()), &dlg, SLOT(accept()));
622
623         cbtn = new QPushButton("Close", &dlg);
624         cbtn->setGeometry(260, 50, 100, 30);
625         connect(cbtn, SIGNAL(clicked()), &dlg, SLOT(reject()));
626         dlg.resize(380, 90);
627
628         if (dlg.exec()) {
629                 sensitive = tmpQRadioButton->isChecked();
630                 find_text = tmpQLineEdit->text();
631                 
632                 QTextDocument::FindFlags flags = 0;
633                 
634                 if (sensitive) {
635                         flags |= QTextDocument::FindCaseSensitively;
636                 }
637                 e->find(find_text, flags);
638         }
639 }
640
641 /**
642  * Searches for next occurence of given text in editor content.
643  * Displays window to set search parameters. If text is found sets cursor
644  * position on it.
645  */
646 void Editor::find_next()
647 {
648         if (!find_text.isEmpty()) {
649                 QTextDocument::FindFlags flags = 0;
650                 
651                 if (sensitive) {
652                         flags |= QTextDocument::FindCaseSensitively;
653                 }
654                 e->find(find_text, flags);
655         }
656 }
657 void Editor::on_actionNew_triggered()
658 {
659 }
660 void Editor::on_actionOpen_triggered()
661 {
662 }
663 void Editor::on_actionSave_triggered()
664 {
665 }
666 void Editor::on_actionSave_as_triggered()
667 {
668 }
669 void Editor::on_actionQuit_triggered()
670 {
671 }
672 void Editor::on_actionCopy_triggered()
673 {
674 }
675 void Editor::on_actionPaste_triggered()
676 {
677 }
678 void Editor::on_actionCut_triggered()
679 {
680 }
681 void Editor::on_actionClear_all_triggered()
682 {
683 }
684 void Editor::on_actionFind_triggered()
685 {
686 }
687 void Editor::on_actionFind_Next_triggered()
688 {
689 }
690
691 /**
692  * Program main function.
693  * argv[1] is mandatory and should be a path to the home directory of
694  * application (same as in configuration file).
695  * @param argc Number of program arguments
696  * @param argv Program arguments
697  */
698 int main(int argc, char **argv)
699 {
700         QApplication app(argc, argv);
701         editor = new Editor(argv[1], NULL);
702         editor->resize(600, 400);
703         editor->show();
704         return app.exec();
705 }
706