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