1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Robert Bieber
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "editorwindow.h"
23 #include "projectmodel.h"
24 #include "ui_editorwindow.h"
26 #include <QDesktopWidget>
27 #include <QFileSystemModel>
29 #include <QFileDialog>
30 #include <QGraphicsScene>
32 EditorWindow::EditorWindow(QWidget
*parent
) :
33 QMainWindow(parent
), ui(new Ui::EditorWindow
), parseTreeSelection(0)
36 prefs
= new PreferencesDialog(this);
44 EditorWindow::~EditorWindow()
54 void EditorWindow::loadTabFromSkinFile(QString fileName
)
56 /* Checking to see if the file is already open */
57 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
59 TabContent
* current
= dynamic_cast<TabContent
*>
60 (ui
->editorTabs
->widget(i
));
61 if(current
->file() == fileName
)
63 ui
->editorTabs
->setCurrentIndex(i
);
68 /* Adding a new document*/
69 SkinDocument
* doc
= new SkinDocument(parseStatus
, fileName
, project
,
72 ui
->editorTabs
->setCurrentWidget(doc
);
76 void EditorWindow::loadConfigTab(ConfigDocument
* doc
)
78 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
80 TabContent
* current
= dynamic_cast<TabContent
*>
81 (ui
->editorTabs
->widget(i
));
82 if(current
->file() == doc
->file())
84 ui
->editorTabs
->setCurrentIndex(i
);
91 ui
->editorTabs
->setCurrentWidget(doc
);
93 QObject::connect(doc
, SIGNAL(titleChanged(QString
)),
94 this, SLOT(tabTitleChanged(QString
)));
97 void EditorWindow::loadSettings()
102 /* Main Window location */
103 settings
.beginGroup("EditorWindow");
104 QSize size
= settings
.value("size").toSize();
105 QPoint pos
= settings
.value("position").toPoint();
106 QByteArray state
= settings
.value("state").toByteArray();
109 if(!(size
.isNull() || pos
.isNull() || state
.isNull()))
118 void EditorWindow::saveSettings()
123 /* Saving window and panel positions */
124 settings
.beginGroup("EditorWindow");
125 settings
.setValue("position", pos());
126 settings
.setValue("size", size());
127 settings
.setValue("state", saveState());
131 void EditorWindow::setupUI()
133 /* Connecting the tab bar signals */
134 QObject::connect(ui
->editorTabs
, SIGNAL(currentChanged(int)),
135 this, SLOT(shiftTab(int)));
136 QObject::connect(ui
->editorTabs
, SIGNAL(tabCloseRequested(int)),
137 this, SLOT(closeTab(int)));
139 /* Connecting the code gen button */
140 QObject::connect(ui
->fromTree
, SIGNAL(pressed()),
141 this, SLOT(updateCurrent()));
143 /* Connecting the preferences dialog */
144 QObject::connect(ui
->actionPreferences
, SIGNAL(triggered()),
145 prefs
, SLOT(exec()));
147 /* Setting up the parse status label */
148 parseStatus
= new QLabel(this);
149 ui
->statusbar
->addPermanentWidget(parseStatus
);
151 /* Setting the selection for parse tree highlighting initially NULL */
152 parseTreeSelection
= 0;
154 /* Adding the skin viewer */
155 viewer
= new SkinViewer(this);
156 ui
->skinPreviewLayout
->addWidget(viewer
);
158 /* Positioning the device settings dialog */
159 deviceDock
= new QDockWidget(tr("Device Configuration"), this);
160 deviceConfig
= new DeviceState(deviceDock
);
162 deviceDock
->setObjectName("deviceDock");
163 deviceDock
->setWidget(deviceConfig
);
164 deviceDock
->setFloating(true);
168 void EditorWindow::setupMenus()
170 /* Connecting panel show actions */
171 QObject::connect(ui
->actionFile_Panel
, SIGNAL(triggered()),
172 this, SLOT(showPanel()));
173 QObject::connect(ui
->actionDisplay_Panel
, SIGNAL(triggered()),
174 this, SLOT(showPanel()));
175 QObject::connect(ui
->actionPreview_Panel
, SIGNAL(triggered()),
176 this, SLOT(showPanel()));
177 QObject::connect(ui
->actionDevice_Configuration
, SIGNAL(triggered()),
178 deviceDock
, SLOT(show()));
180 /* Connecting the document management actions */
181 QObject::connect(ui
->actionNew_Document
, SIGNAL(triggered()),
182 this, SLOT(newTab()));
183 QObject::connect(ui
->actionToolbarNew
, SIGNAL(triggered()),
184 this, SLOT(newTab()));
186 QObject::connect(ui
->actionClose_Document
, SIGNAL(triggered()),
187 this, SLOT(closeCurrent()));
189 QObject::connect(ui
->actionSave_Document
, SIGNAL(triggered()),
190 this, SLOT(saveCurrent()));
191 QObject::connect(ui
->actionSave_Document_As
, SIGNAL(triggered()),
192 this, SLOT(saveCurrentAs()));
193 QObject::connect(ui
->actionToolbarSave
, SIGNAL(triggered()),
194 this, SLOT(saveCurrent()));
196 QObject::connect(ui
->actionOpen_Document
, SIGNAL(triggered()),
197 this, SLOT(openFile()));
198 QObject::connect(ui
->actionToolbarOpen
, SIGNAL(triggered()),
199 this, SLOT(openFile()));
201 QObject::connect(ui
->actionOpen_Project
, SIGNAL(triggered()),
202 this, SLOT(openProject()));
204 /* Connecting the edit menu */
205 QObject::connect(ui
->actionUndo
, SIGNAL(triggered()),
207 QObject::connect(ui
->actionRedo
, SIGNAL(triggered()),
209 QObject::connect(ui
->actionCut
, SIGNAL(triggered()),
211 QObject::connect(ui
->actionCopy
, SIGNAL(triggered()),
213 QObject::connect(ui
->actionPaste
, SIGNAL(triggered()),
214 this, SLOT(paste()));
215 QObject::connect(ui
->actionFind_Replace
, SIGNAL(triggered()),
216 this, SLOT(findReplace()));
219 void EditorWindow::addTab(TabContent
*doc
)
221 ui
->editorTabs
->addTab(doc
, doc
->title());
223 /* Connecting to title change events */
224 QObject::connect(doc
, SIGNAL(titleChanged(QString
)),
225 this, SLOT(tabTitleChanged(QString
)));
226 QObject::connect(doc
, SIGNAL(lineChanged(int)),
227 this, SLOT(lineChanged(int)));
229 /* Connecting to settings change events */
230 if(doc
->type() == TabContent::Skin
)
231 dynamic_cast<SkinDocument
*>(doc
)->connectPrefs(prefs
);
235 void EditorWindow::newTab()
237 SkinDocument
* doc
= new SkinDocument(parseStatus
, project
, deviceConfig
);
239 ui
->editorTabs
->setCurrentWidget(doc
);
242 void EditorWindow::shiftTab(int index
)
244 TabContent
* widget
= dynamic_cast<TabContent
*>
245 (ui
->editorTabs
->currentWidget());
248 ui
->parseTree
->setModel(0);
249 ui
->actionSave_Document
->setEnabled(false);
250 ui
->actionSave_Document_As
->setEnabled(false);
251 ui
->actionClose_Document
->setEnabled(false);
252 ui
->actionToolbarSave
->setEnabled(false);
253 ui
->fromTree
->setEnabled(false);
254 ui
->actionUndo
->setEnabled(false);
255 ui
->actionRedo
->setEnabled(false);
256 ui
->actionCut
->setEnabled(false);
257 ui
->actionCopy
->setEnabled(false);
258 ui
->actionPaste
->setEnabled(false);
259 ui
->actionFind_Replace
->setEnabled(false);
262 else if(widget
->type() == TabContent::Config
)
264 ui
->actionSave_Document
->setEnabled(true);
265 ui
->actionSave_Document_As
->setEnabled(true);
266 ui
->actionClose_Document
->setEnabled(true);
267 ui
->actionToolbarSave
->setEnabled(true);
268 ui
->actionUndo
->setEnabled(false);
269 ui
->actionRedo
->setEnabled(false);
270 ui
->actionCut
->setEnabled(false);
271 ui
->actionCopy
->setEnabled(false);
272 ui
->actionPaste
->setEnabled(false);
273 ui
->actionFind_Replace
->setEnabled(false);
276 else if(widget
->type() == TabContent::Skin
)
278 /* Syncing the tree view and the status bar */
279 SkinDocument
* doc
= dynamic_cast<SkinDocument
*>(widget
);
280 ui
->parseTree
->setModel(doc
->getModel());
281 parseStatus
->setText(doc
->getStatus());
283 ui
->actionSave_Document
->setEnabled(true);
284 ui
->actionSave_Document_As
->setEnabled(true);
285 ui
->actionClose_Document
->setEnabled(true);
286 ui
->actionToolbarSave
->setEnabled(true);
287 ui
->fromTree
->setEnabled(true);
289 ui
->actionUndo
->setEnabled(true);
290 ui
->actionRedo
->setEnabled(true);
291 ui
->actionCut
->setEnabled(true);
292 ui
->actionCopy
->setEnabled(true);
293 ui
->actionPaste
->setEnabled(true);
294 ui
->actionFind_Replace
->setEnabled(true);
298 /* Syncing the preview */
299 viewer
->setScene(doc
->scene());
303 /* Hiding all the find/replace dialogs */
304 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
305 if(dynamic_cast<TabContent
*>(ui
->editorTabs
->widget(i
))->type() ==
307 dynamic_cast<SkinDocument
*>(ui
->editorTabs
->widget(i
))->hideFind();
311 bool EditorWindow::closeTab(int index
)
313 TabContent
* widget
= dynamic_cast<TabContent
*>
314 (ui
->editorTabs
->widget(index
));
315 if(widget
->requestClose())
317 ui
->editorTabs
->removeTab(index
);
318 widget
->deleteLater();
325 void EditorWindow::closeCurrent()
327 closeTab(ui
->editorTabs
->currentIndex());
330 void EditorWindow::saveCurrent()
332 if(ui
->editorTabs
->currentIndex() >= 0)
333 dynamic_cast<TabContent
*>(ui
->editorTabs
->currentWidget())->save();
336 void EditorWindow::saveCurrentAs()
338 if(ui
->editorTabs
->currentIndex() >= 0)
339 dynamic_cast<TabContent
*>(ui
->editorTabs
->currentWidget())->saveAs();
342 void EditorWindow::openFile()
344 QStringList fileNames
;
347 settings
.beginGroup("SkinDocument");
348 QString directory
= settings
.value("defaultDirectory", "").toString();
349 fileNames
= QFileDialog::getOpenFileNames(this, tr("Open Files"), directory
,
350 SkinDocument::fileFilter());
352 for(int i
= 0; i
< fileNames
.count(); i
++)
354 if(!QFile::exists(fileNames
[i
]))
357 QString current
= fileNames
[i
];
359 loadTabFromSkinFile(current
);
361 /* And setting the new default directory */
362 current
.chop(current
.length() - current
.lastIndexOf('/') - 1);
363 settings
.setValue("defaultDirectory", current
);
370 void EditorWindow::openProject()
375 settings
.beginGroup("ProjectModel");
376 QString directory
= settings
.value("defaultDirectory", "").toString();
377 fileName
= QFileDialog::getOpenFileName(this, tr("Open Project"), directory
,
378 ProjectModel::fileFilter());
380 if(QFile::exists(fileName
))
386 project
= new ProjectModel(fileName
, this);
387 ui
->projectTree
->setModel(project
);
389 if(project
->getSetting("#screenwidth") != "")
390 deviceConfig
->setData("screenwidth",
391 project
->getSetting("#screenwidth"));
392 if(project
->getSetting("#screenheight") != "")
393 deviceConfig
->setData("screenheight",
394 project
->getSetting("#screenheight"));
396 QObject::connect(ui
->projectTree
, SIGNAL(activated(QModelIndex
)),
397 project
, SLOT(activated(QModelIndex
)));
399 fileName
.chop(fileName
.length() - fileName
.lastIndexOf('/') - 1);
400 settings
.setValue("defaultDirectory", fileName
);
402 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
404 TabContent
* doc
= dynamic_cast<TabContent
*>
405 (ui
->editorTabs
->widget(i
));
406 if(doc
->type() == TabContent::Skin
)
408 dynamic_cast<SkinDocument
*>(doc
)->setProject(project
);
409 if(i
== ui
->editorTabs
->currentIndex())
411 viewer
->setScene(dynamic_cast<SkinDocument
*>(doc
)->scene());
422 void EditorWindow::configFileChanged(QString configFile
)
425 if(QFile::exists(configFile
))
431 project
= new ProjectModel(configFile
, this);
432 ui
->projectTree
->setModel(project
);
434 QObject::connect(ui
->projectTree
, SIGNAL(activated(QModelIndex
)),
435 project
, SLOT(activated(QModelIndex
)));
437 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
439 TabContent
* doc
= dynamic_cast<TabContent
*>
440 (ui
->editorTabs
->widget(i
));
441 if(doc
->type() == TabContent::Skin
)
443 dynamic_cast<SkinDocument
*>(doc
)->setProject(project
);
444 if(i
== ui
->editorTabs
->currentIndex())
446 viewer
->setScene(dynamic_cast<SkinDocument
*>(doc
)->scene());
456 void EditorWindow::tabTitleChanged(QString title
)
458 TabContent
* sender
= dynamic_cast<TabContent
*>(QObject::sender());
459 ui
->editorTabs
->setTabText(ui
->editorTabs
->indexOf(sender
), title
);
462 void EditorWindow::showPanel()
464 if(sender() == ui
->actionFile_Panel
)
465 ui
->projectDock
->setVisible(true);
466 if(sender() == ui
->actionPreview_Panel
)
467 ui
->skinPreviewDock
->setVisible(true);
468 if(sender() == ui
->actionDisplay_Panel
)
469 ui
->parseTreeDock
->setVisible(true);
472 void EditorWindow::closeEvent(QCloseEvent
* event
)
477 /* Closing all the tabs */
478 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
480 if(!dynamic_cast<TabContent
*>
481 (ui
->editorTabs
->widget(i
))->requestClose())
491 void EditorWindow::updateCurrent()
493 if(ui
->editorTabs
->currentIndex() < 0)
496 dynamic_cast<SkinDocument
*>
497 (ui
->editorTabs
->currentWidget())->genCode();
500 void EditorWindow::lineChanged(int line
)
502 ui
->parseTree
->collapseAll();
503 ParseTreeModel
* model
= dynamic_cast<ParseTreeModel
*>
504 (ui
->parseTree
->model());
505 parseTreeSelection
= new QItemSelectionModel(model
);
506 expandLine(model
, QModelIndex(), line
);
508 ui
->parseTree
->setSelectionModel(parseTreeSelection
);
512 void EditorWindow::undo()
514 TabContent
* doc
= dynamic_cast<TabContent
*>
515 (ui
->editorTabs
->currentWidget());
516 if(doc
->type() == TabContent::Skin
)
517 dynamic_cast<SkinDocument
*>(doc
)->getEditor()->undo();
520 void EditorWindow::redo()
522 TabContent
* doc
= dynamic_cast<TabContent
*>
523 (ui
->editorTabs
->currentWidget());
524 if(doc
->type() == TabContent::Skin
)
525 dynamic_cast<SkinDocument
*>(doc
)->getEditor()->redo();
529 void EditorWindow::cut()
531 TabContent
* doc
= dynamic_cast<TabContent
*>
532 (ui
->editorTabs
->currentWidget());
533 if(doc
->type() == TabContent::Skin
)
534 dynamic_cast<SkinDocument
*>(doc
)->getEditor()->cut();
537 void EditorWindow::copy()
539 TabContent
* doc
= dynamic_cast<TabContent
*>
540 (ui
->editorTabs
->currentWidget());
541 if(doc
->type() == TabContent::Skin
)
542 dynamic_cast<SkinDocument
*>(doc
)->getEditor()->copy();
545 void EditorWindow::paste()
547 TabContent
* doc
= dynamic_cast<TabContent
*>
548 (ui
->editorTabs
->currentWidget());
549 if(doc
->type() == TabContent::Skin
)
550 dynamic_cast<SkinDocument
*>(doc
)->getEditor()->paste();
553 void EditorWindow::findReplace()
555 TabContent
* doc
= dynamic_cast<TabContent
*>
556 (ui
->editorTabs
->currentWidget());
557 if(doc
->type() == TabContent::Skin
)
558 dynamic_cast<SkinDocument
*>(doc
)->showFind();
562 void EditorWindow::expandLine(ParseTreeModel
* model
, QModelIndex parent
,
565 for(int i
= 0; i
< model
->rowCount(parent
); i
++)
567 QModelIndex dataType
= model
->index(i
, ParseTreeModel::typeColumn
,
569 QModelIndex dataVal
= model
->index(i
, ParseTreeModel::valueColumn
,
571 QModelIndex data
= model
->index(i
, ParseTreeModel::lineColumn
, parent
);
572 QModelIndex recurse
= model
->index(i
, 0, parent
);
574 expandLine(model
, recurse
, line
);
576 if(model
->data(data
, Qt::DisplayRole
) == line
)
578 ui
->parseTree
->expand(parent
);
579 ui
->parseTree
->expand(data
);
580 ui
->parseTree
->scrollTo(parent
, QAbstractItemView::PositionAtTop
);
582 parseTreeSelection
->select(data
, QItemSelectionModel::Select
);
583 parseTreeSelection
->select(dataType
, QItemSelectionModel::Select
);
584 parseTreeSelection
->select(dataVal
, QItemSelectionModel::Select
);
590 void EditorWindow::sizeColumns()
592 /* Setting the column widths */
593 ui
->parseTree
->resizeColumnToContents(ParseTreeModel::lineColumn
);
594 ui
->parseTree
->resizeColumnToContents(ParseTreeModel::typeColumn
);
595 ui
->parseTree
->resizeColumnToContents(ParseTreeModel::valueColumn
);