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