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