Fix problem with partial loading of files
[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         editor->append(textStream.readAll());
92 //      while (!file.atEnd()) {
93 //              editor->append(textStream.readLine());
94 //      }
95
96         file.close();
97
98         editor->repaint();
99         setWindowTitle(fileName);
100 }
101
102 /**
103  * Saves editor content to the given filename.
104  * @param fileName File name of the file where content should be saved.
105  */
106 void Editor::save(const char *fileName)
107 {
108         QFile file(fileName);
109         if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
110                 return;
111
112         file.reset();
113         file.write(editor->toPlainText().toAscii().data(), editor->toPlainText().length());
114         file.close();
115 }
116
117 /**
118  * Invokes compiler in the giving mode.
119  * @param mode Mode of compilation. Possible values:
120  *             - COMP_MODE - compilation mode
121  *             - GEN_MODE - program generation mode
122  *             - ALL_MODE - compilation & generation mode.
123  */
124 void Editor::compile(int mode)
125 {
126         char cmd[255];
127         messages->setReadOnly(FALSE);
128         messages->clear();
129         messages->repaint();
130
131         /*i = fname.find('.');*/
132         /* if (i>=0) {*/
133
134         /*  fn.truncate(i);*/
135         switch(mode) {
136         case COMP_MODE:
137                 sprintf(cmd, "%s %s > comp_data!", compiler_path.toStdString().c_str(),
138                                                         fname.toStdString().c_str());
139                 break;
140         case GEN_MODE:
141                 sprintf(cmd, "%s %s > comp_data!", gen_path.toStdString().c_str(),
142                                                         fname.toStdString().c_str());
143                 break;
144         case ALL_MODE:
145                 sprintf(cmd, "%s %s > comp_data!", compiler_path.toStdString().c_str(),
146                                                         fname.toStdString().c_str());
147                 system(cmd);
148                 sprintf(cmd, "%s %s >> comp_data!", gen_path.toStdString().c_str(),
149                                                         fname.toStdString().c_str());
150         break;
151         }
152
153         system(cmd);
154         QFile f("comp_data!");
155         if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
156                 return;
157
158         QTextStream t(&f);
159         while (!t.atEnd()) {
160                 QString s = t.readLine();
161                 messages->append(s);
162         }
163         f.close();
164
165         messages->setReadOnly(TRUE);
166
167         messages->repaint();
168         unlink("comp_data!");
169         /*}*/
170 }
171
172 /**
173  * Empties editor content.
174  */
175 void Editor::on_actionNew_triggered()
176 {
177         on_actionClear_all_triggered();
178         fname.sprintf("%s", "");
179 }
180
181 /**
182  * Displays additional window 
183  */
184 void Editor::on_actionOpen_triggered()
185 {
186         QString fn = QFileDialog::getOpenFileName(this, "Load file", file_path, "*.log");
187         if (!fn.isEmpty())
188                 load(fn.toAscii().data());
189 }
190
191 /**
192  * Saves editor content to the file.
193  * If content has been read from file, it is written to this file. Otherwise
194  * dialog is shown to save content to the specified by user, file.
195  */
196 void Editor::on_actionSave_triggered()
197 {
198         if (fname.isEmpty()) {
199                 QString fn = QFileDialog::getSaveFileName(this, "Save file", 
200                                                         file_path, "*.log");
201                 if (!fn.isEmpty()) {
202                         fname.sprintf("%s", fn.toAscii().data());
203                         save(fn.toAscii().data());
204                 }
205         } else {
206                 save(fname.toAscii().data());
207         }
208         setWindowTitle(fname);
209 }
210
211 /**
212  * Saves editor content to the file.
213  * Forces saving editor content to the new file. Special dialog is shown for
214  * that purpose.
215  */
216 void Editor::on_actionSave_as_triggered()
217 {
218         QString fn = QFileDialog::getSaveFileName(this, "Save file as",
219                                                         file_path, "*.log");
220         if (!fn.isEmpty()) {
221                 fname.sprintf("%s", fn.toAscii().data());
222                 save(fn.toAscii().data());
223         }
224         setWindowTitle(fname);
225 }
226 void Editor::on_actionQuit_triggered()
227 {
228         QApplication::instance()->quit();
229 }
230 void Editor::on_actionCopy_triggered()
231 {
232         editor->copy();
233 }
234 void Editor::on_actionPaste_triggered()
235 {
236         editor->paste();
237 }
238 void Editor::on_actionCut_triggered()
239 {
240         editor->cut();
241 }
242 void Editor::on_actionClear_all_triggered()
243 {
244         editor->clear();
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         dialog::FindDialog dialog(this);
255
256         if (dialog.exec()) {
257                 sensitive = dialog.isCaseSensitive();
258                 find_text = dialog.getSearchText();
259                 
260                 QTextDocument::FindFlags flags = 0;
261                 
262                 if (sensitive) {
263                         flags |= QTextDocument::FindCaseSensitively;
264                 }
265
266                 editor->find(find_text, flags);
267         }
268 }
269
270 /**
271  * Searches for next occurence of given text in editor content.
272  * Displays window to set search parameters. If text is found sets cursor
273  * position on it.
274  */
275 void Editor::on_actionFind_Next_triggered()
276 {
277         if (!find_text.isEmpty()) {
278                 QTextDocument::FindFlags flags = 0;
279                 
280                 if (sensitive) {
281                         flags |= QTextDocument::FindCaseSensitively;
282                 }
283                 editor->find(find_text, flags);
284         }
285 }
286
287 /**
288  * Displays window with editor properties
289  */
290 void Editor::on_actionPreferences_triggered()
291 {
292         dialog::PreferencesDialog dialog(this);
293
294         dialog.setCompilerPath(compiler_path);
295         dialog.setFilesPath(file_path);
296         dialog.setGenPath(gen_path);
297
298         if (dialog.exec()) {
299                 compiler_path.sprintf("%s", dialog.getCompilerPath().toStdString().c_str());
300                 gen_path.sprintf("%s",dialog.getGenPath().toStdString().c_str());
301                 file_path.sprintf("%s", dialog.getFilesPath().toStdString().c_str());
302         };
303 }
304
305 /**
306  * Saves and compiles code.
307  */
308 void Editor::on_actionCompile_triggered()
309 {
310         on_actionSave_triggered();
311         compile(COMP_MODE);
312 }
313
314 /**
315  * Generates program.
316  */
317 void Editor::on_actionGen_triggered()
318 {
319         compile(GEN_MODE);
320 }
321
322 /**
323  * Saves, compiles and generates code.
324  */
325 void Editor::on_actionCompile_Gen_triggered()
326 {
327         on_actionSave_triggered();
328         compile(ALL_MODE);
329 }
330
331 void Editor::on_actionProgram_structure_triggered()
332 {
333         dialog::ProgramStructureDialog dialog(this);
334
335         if (dialog.exec()) {
336                 editor->textCursor().insertText(dialog.getCode());
337         }
338 }
339
340 void Editor::on_actionUnit_structure_triggered()
341 {
342         dialog::UnitStructureDialog dialog(this);
343
344         if (dialog.exec()) {
345                 editor->textCursor().insertText(dialog.getCode());
346         }
347 }
348
349 }
350 }
351
352 /**
353  * Program main function.
354  * argv[1] is mandatory and should be a path to the home directory of
355  * application (same as in configuration file).
356  *
357  * @param argc Number of program arguments
358  * @param argv Program arguments
359  */
360 int main(int argc, char **argv)
361 {
362         QApplication app(argc, argv);
363         loglan::vlp::Editor * editor = new loglan::vlp::Editor(argc, argv);
364         editor->show();
365         return app.exec();
366 }
367