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