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