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