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
);
71 ui
->editorTabs
->setCurrentWidget(doc
);
75 void EditorWindow::loadConfigTab(ConfigDocument
* doc
)
77 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
79 TabContent
* current
= dynamic_cast<TabContent
*>
80 (ui
->editorTabs
->widget(i
));
81 if(current
->file() == doc
->file())
83 ui
->editorTabs
->setCurrentIndex(i
);
90 ui
->editorTabs
->setCurrentWidget(doc
);
92 QObject::connect(doc
, SIGNAL(titleChanged(QString
)),
93 this, SLOT(tabTitleChanged(QString
)));
96 void EditorWindow::loadSettings()
101 /* Main Window location */
102 settings
.beginGroup("EditorWindow");
103 QSize size
= settings
.value("size").toSize();
104 QPoint pos
= settings
.value("position").toPoint();
105 QByteArray state
= settings
.value("state").toByteArray();
108 if(!(size
.isNull() || pos
.isNull() || state
.isNull()))
117 void EditorWindow::saveSettings()
122 /* Saving window and panel positions */
123 settings
.beginGroup("EditorWindow");
124 settings
.setValue("position", pos());
125 settings
.setValue("size", size());
126 settings
.setValue("state", saveState());
130 void EditorWindow::setupUI()
132 /* Connecting the tab bar signals */
133 QObject::connect(ui
->editorTabs
, SIGNAL(currentChanged(int)),
134 this, SLOT(shiftTab(int)));
135 QObject::connect(ui
->editorTabs
, SIGNAL(tabCloseRequested(int)),
136 this, SLOT(closeTab(int)));
138 /* Connecting the code gen button */
139 QObject::connect(ui
->fromTree
, SIGNAL(pressed()),
140 this, SLOT(updateCurrent()));
142 /* Connecting the preferences dialog */
143 QObject::connect(ui
->actionPreferences
, SIGNAL(triggered()),
144 prefs
, SLOT(exec()));
146 /* Setting up the parse status label */
147 parseStatus
= new QLabel(this);
148 ui
->statusbar
->addPermanentWidget(parseStatus
);
150 /* Setting the selection for parse tree highlighting initially NULL */
151 parseTreeSelection
= 0;
153 /* Adding the skin viewer */
154 viewer
= new SkinViewer(this);
155 ui
->skinPreviewLayout
->addWidget(viewer
);
157 /* Positioning the device settings dialog */
158 deviceDock
= new QDockWidget(tr("Device Configuration"), this);
159 deviceConfig
= new DeviceState(deviceDock
);
161 deviceDock
->setObjectName("deviceDock");
162 deviceDock
->setWidget(deviceConfig
);
163 deviceDock
->setFloating(true);
167 void EditorWindow::setupMenus()
169 /* Connecting panel show actions */
170 QObject::connect(ui
->actionFile_Panel
, SIGNAL(triggered()),
171 this, SLOT(showPanel()));
172 QObject::connect(ui
->actionDisplay_Panel
, SIGNAL(triggered()),
173 this, SLOT(showPanel()));
174 QObject::connect(ui
->actionPreview_Panel
, SIGNAL(triggered()),
175 this, SLOT(showPanel()));
176 QObject::connect(ui
->actionDevice_Configuration
, SIGNAL(triggered()),
177 deviceDock
, SLOT(show()));
179 /* Connecting the document management actions */
180 QObject::connect(ui
->actionNew_Document
, SIGNAL(triggered()),
181 this, SLOT(newTab()));
182 QObject::connect(ui
->actionToolbarNew
, SIGNAL(triggered()),
183 this, SLOT(newTab()));
185 QObject::connect(ui
->actionClose_Document
, SIGNAL(triggered()),
186 this, SLOT(closeCurrent()));
188 QObject::connect(ui
->actionSave_Document
, SIGNAL(triggered()),
189 this, SLOT(saveCurrent()));
190 QObject::connect(ui
->actionSave_Document_As
, SIGNAL(triggered()),
191 this, SLOT(saveCurrentAs()));
192 QObject::connect(ui
->actionToolbarSave
, SIGNAL(triggered()),
193 this, SLOT(saveCurrent()));
195 QObject::connect(ui
->actionOpen_Document
, SIGNAL(triggered()),
196 this, SLOT(openFile()));
197 QObject::connect(ui
->actionToolbarOpen
, SIGNAL(triggered()),
198 this, SLOT(openFile()));
200 QObject::connect(ui
->actionOpen_Project
, SIGNAL(triggered()),
201 this, SLOT(openProject()));
204 void EditorWindow::addTab(TabContent
*doc
)
206 ui
->editorTabs
->addTab(doc
, doc
->title());
208 /* Connecting to title change events */
209 QObject::connect(doc
, SIGNAL(titleChanged(QString
)),
210 this, SLOT(tabTitleChanged(QString
)));
211 QObject::connect(doc
, SIGNAL(lineChanged(int)),
212 this, SLOT(lineChanged(int)));
214 /* Connecting to settings change events */
215 if(doc
->type() == TabContent::Skin
)
216 dynamic_cast<SkinDocument
*>(doc
)->connectPrefs(prefs
);
220 void EditorWindow::newTab()
222 SkinDocument
* doc
= new SkinDocument(parseStatus
, project
);
224 ui
->editorTabs
->setCurrentWidget(doc
);
227 void EditorWindow::shiftTab(int index
)
229 TabContent
* widget
= dynamic_cast<TabContent
*>
230 (ui
->editorTabs
->currentWidget());
233 ui
->parseTree
->setModel(0);
234 ui
->actionSave_Document
->setEnabled(false);
235 ui
->actionSave_Document_As
->setEnabled(false);
236 ui
->actionClose_Document
->setEnabled(false);
237 ui
->actionToolbarSave
->setEnabled(false);
238 ui
->fromTree
->setEnabled(false);
241 else if(widget
->type() == TabContent::Config
)
243 ui
->actionSave_Document
->setEnabled(true);
244 ui
->actionSave_Document_As
->setEnabled(true);
245 ui
->actionClose_Document
->setEnabled(true);
246 ui
->actionToolbarSave
->setEnabled(true);
249 else if(widget
->type() == TabContent::Skin
)
251 /* Syncing the tree view and the status bar */
252 SkinDocument
* doc
= dynamic_cast<SkinDocument
*>(widget
);
253 ui
->parseTree
->setModel(doc
->getModel());
254 parseStatus
->setText(doc
->getStatus());
256 ui
->actionSave_Document
->setEnabled(true);
257 ui
->actionSave_Document_As
->setEnabled(true);
258 ui
->actionClose_Document
->setEnabled(true);
259 ui
->actionToolbarSave
->setEnabled(true);
260 ui
->fromTree
->setEnabled(true);
264 /* Syncing the preview */
265 viewer
->setScene(doc
->scene());
270 bool EditorWindow::closeTab(int index
)
272 TabContent
* widget
= dynamic_cast<TabContent
*>
273 (ui
->editorTabs
->widget(index
));
274 if(widget
->requestClose())
276 ui
->editorTabs
->removeTab(index
);
277 widget
->deleteLater();
284 void EditorWindow::closeCurrent()
286 closeTab(ui
->editorTabs
->currentIndex());
289 void EditorWindow::saveCurrent()
291 if(ui
->editorTabs
->currentIndex() >= 0)
292 dynamic_cast<TabContent
*>(ui
->editorTabs
->currentWidget())->save();
295 void EditorWindow::saveCurrentAs()
297 if(ui
->editorTabs
->currentIndex() >= 0)
298 dynamic_cast<TabContent
*>(ui
->editorTabs
->currentWidget())->saveAs();
301 void EditorWindow::openFile()
303 QStringList fileNames
;
306 settings
.beginGroup("SkinDocument");
307 QString directory
= settings
.value("defaultDirectory", "").toString();
308 fileNames
= QFileDialog::getOpenFileNames(this, tr("Open Files"), directory
,
309 SkinDocument::fileFilter());
311 for(int i
= 0; i
< fileNames
.count(); i
++)
313 if(!QFile::exists(fileNames
[i
]))
316 QString current
= fileNames
[i
];
318 loadTabFromSkinFile(current
);
320 /* And setting the new default directory */
321 current
.chop(current
.length() - current
.lastIndexOf('/') - 1);
322 settings
.setValue("defaultDirectory", current
);
329 void EditorWindow::openProject()
334 settings
.beginGroup("ProjectModel");
335 QString directory
= settings
.value("defaultDirectory", "").toString();
336 fileName
= QFileDialog::getOpenFileName(this, tr("Open Project"), directory
,
337 ProjectModel::fileFilter());
339 if(QFile::exists(fileName
))
345 project
= new ProjectModel(fileName
, this);
346 ui
->projectTree
->setModel(project
);
348 QObject::connect(ui
->projectTree
, SIGNAL(activated(QModelIndex
)),
349 project
, SLOT(activated(QModelIndex
)));
351 fileName
.chop(fileName
.length() - fileName
.lastIndexOf('/') - 1);
352 settings
.setValue("defaultDirectory", fileName
);
354 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
356 TabContent
* doc
= dynamic_cast<TabContent
*>
357 (ui
->editorTabs
->widget(i
));
358 if(doc
->type() == TabContent::Skin
)
360 dynamic_cast<SkinDocument
*>(doc
)->setProject(project
);
361 if(i
== ui
->editorTabs
->currentIndex())
363 viewer
->setScene(dynamic_cast<SkinDocument
*>(doc
)->scene());
374 void EditorWindow::configFileChanged(QString configFile
)
377 if(QFile::exists(configFile
))
383 project
= new ProjectModel(configFile
, this);
384 ui
->projectTree
->setModel(project
);
386 QObject::connect(ui
->projectTree
, SIGNAL(activated(QModelIndex
)),
387 project
, SLOT(activated(QModelIndex
)));
389 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
391 TabContent
* doc
= dynamic_cast<TabContent
*>
392 (ui
->editorTabs
->widget(i
));
393 if(doc
->type() == TabContent::Skin
)
395 dynamic_cast<SkinDocument
*>(doc
)->setProject(project
);
396 if(i
== ui
->editorTabs
->currentIndex())
398 viewer
->setScene(dynamic_cast<SkinDocument
*>(doc
)->scene());
408 void EditorWindow::tabTitleChanged(QString title
)
410 TabContent
* sender
= dynamic_cast<TabContent
*>(QObject::sender());
411 ui
->editorTabs
->setTabText(ui
->editorTabs
->indexOf(sender
), title
);
414 void EditorWindow::showPanel()
416 if(sender() == ui
->actionFile_Panel
)
417 ui
->projectDock
->setVisible(true);
418 if(sender() == ui
->actionPreview_Panel
)
419 ui
->skinPreviewDock
->setVisible(true);
420 if(sender() == ui
->actionDisplay_Panel
)
421 ui
->parseTreeDock
->setVisible(true);
424 void EditorWindow::closeEvent(QCloseEvent
* event
)
429 /* Closing all the tabs */
430 for(int i
= 0; i
< ui
->editorTabs
->count(); i
++)
432 if(!dynamic_cast<TabContent
*>
433 (ui
->editorTabs
->widget(i
))->requestClose())
443 void EditorWindow::updateCurrent()
445 if(ui
->editorTabs
->currentIndex() < 0)
448 dynamic_cast<SkinDocument
*>
449 (ui
->editorTabs
->currentWidget())->genCode();
452 void EditorWindow::lineChanged(int line
)
454 ui
->parseTree
->collapseAll();
455 ParseTreeModel
* model
= dynamic_cast<ParseTreeModel
*>
456 (ui
->parseTree
->model());
457 parseTreeSelection
= new QItemSelectionModel(model
);
458 expandLine(model
, QModelIndex(), line
);
460 ui
->parseTree
->setSelectionModel(parseTreeSelection
);
464 void EditorWindow::expandLine(ParseTreeModel
* model
, QModelIndex parent
,
467 for(int i
= 0; i
< model
->rowCount(parent
); i
++)
469 QModelIndex dataType
= model
->index(i
, ParseTreeModel::typeColumn
,
471 QModelIndex dataVal
= model
->index(i
, ParseTreeModel::valueColumn
,
473 QModelIndex data
= model
->index(i
, ParseTreeModel::lineColumn
, parent
);
474 QModelIndex recurse
= model
->index(i
, 0, parent
);
476 expandLine(model
, recurse
, line
);
478 if(model
->data(data
, Qt::DisplayRole
) == line
)
480 ui
->parseTree
->expand(parent
);
481 ui
->parseTree
->expand(data
);
482 ui
->parseTree
->scrollTo(parent
, QAbstractItemView::PositionAtTop
);
484 parseTreeSelection
->select(data
, QItemSelectionModel::Select
);
485 parseTreeSelection
->select(dataType
, QItemSelectionModel::Select
);
486 parseTreeSelection
->select(dataVal
, QItemSelectionModel::Select
);
492 void EditorWindow::sizeColumns()
494 /* Setting the column widths */
495 ui
->parseTree
->resizeColumnToContents(ParseTreeModel::lineColumn
);
496 ui
->parseTree
->resizeColumnToContents(ParseTreeModel::typeColumn
);
497 ui
->parseTree
->resizeColumnToContents(ParseTreeModel::valueColumn
);