Theme Editor: Fixed some resource alias issues, implemented device configuration...
[kugel-rb.git] / utils / themeeditor / gui / editorwindow.cpp
blob1aec46a7cca210b57cc78e50743f381bfde0e6c3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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>
28 #include <QSettings>
29 #include <QFileDialog>
30 #include <QGraphicsScene>
32 EditorWindow::EditorWindow(QWidget *parent) :
33 QMainWindow(parent),
34 ui(new Ui::EditorWindow)
36 ui->setupUi(this);
37 prefs = new PreferencesDialog(this);
38 project = 0;
39 loadSettings();
40 setupUI();
41 setupMenus();
44 void EditorWindow::loadTabFromSkinFile(QString fileName)
46 /* Checking to see if the file is already open */
47 for(int i = 0; i < ui->editorTabs->count(); i++)
49 TabContent* current = dynamic_cast<TabContent*>
50 (ui->editorTabs->widget(i));
51 if(current->file() == fileName)
53 ui->editorTabs->setCurrentIndex(i);
54 return;
58 /* Adding a new document*/
59 SkinDocument* doc = new SkinDocument(parseStatus, fileName, project);
60 addTab(doc);
61 ui->editorTabs->setCurrentWidget(doc);
65 void EditorWindow::loadConfigTab(ConfigDocument* doc)
67 for(int i = 0; i < ui->editorTabs->count(); i++)
69 TabContent* current = dynamic_cast<TabContent*>
70 (ui->editorTabs->widget(i));
71 if(current->file() == doc->file())
73 ui->editorTabs->setCurrentIndex(i);
74 doc->deleteLater();
75 return;
79 addTab(doc);
80 ui->editorTabs->setCurrentWidget(doc);
82 QObject::connect(doc, SIGNAL(titleChanged(QString)),
83 this, SLOT(tabTitleChanged(QString)));
86 void EditorWindow::loadSettings()
89 QSettings settings;
91 /* Main Window location */
92 settings.beginGroup("EditorWindow");
93 QSize size = settings.value("size").toSize();
94 QPoint pos = settings.value("position").toPoint();
95 QByteArray state = settings.value("state").toByteArray();
96 settings.endGroup();
98 if(!(size.isNull() || pos.isNull() || state.isNull()))
100 resize(size);
101 move(pos);
102 restoreState(state);
107 void EditorWindow::saveSettings()
110 QSettings settings;
112 /* Saving window and panel positions */
113 settings.beginGroup("EditorWindow");
114 settings.setValue("position", pos());
115 settings.setValue("size", size());
116 settings.setValue("state", saveState());
117 settings.endGroup();
120 void EditorWindow::setupUI()
122 /* Connecting the tab bar signals */
123 QObject::connect(ui->editorTabs, SIGNAL(currentChanged(int)),
124 this, SLOT(shiftTab(int)));
125 QObject::connect(ui->editorTabs, SIGNAL(tabCloseRequested(int)),
126 this, SLOT(closeTab(int)));
128 /* Connecting the code gen button */
129 QObject::connect(ui->fromTree, SIGNAL(pressed()),
130 this, SLOT(updateCurrent()));
132 /* Connecting the preferences dialog */
133 QObject::connect(ui->actionPreferences, SIGNAL(triggered()),
134 prefs, SLOT(exec()));
136 /* Setting up the parse status label */
137 parseStatus = new QLabel(this);
138 ui->statusbar->addPermanentWidget(parseStatus);
140 /* Setting the selection for parse tree highlighting initially NULL */
141 parseTreeSelection = 0;
143 /* Adding the skin viewer */
144 viewer = new SkinViewer(this);
145 ui->skinPreviewLayout->addWidget(viewer);
147 /* Positioning the device settings dialog */
148 QPoint thisPos = pos();
149 deviceConfig.move(thisPos.x() + width() / 4, thisPos.y() + height() / 4);
153 void EditorWindow::setupMenus()
155 /* Connecting panel show actions */
156 QObject::connect(ui->actionFile_Panel, SIGNAL(triggered()),
157 this, SLOT(showPanel()));
158 QObject::connect(ui->actionDisplay_Panel, SIGNAL(triggered()),
159 this, SLOT(showPanel()));
160 QObject::connect(ui->actionPreview_Panel, SIGNAL(triggered()),
161 this, SLOT(showPanel()));
162 QObject::connect(ui->actionDevice_Configuration, SIGNAL(triggered()),
163 &deviceConfig, SLOT(show()));
165 /* Connecting the document management actions */
166 QObject::connect(ui->actionNew_Document, SIGNAL(triggered()),
167 this, SLOT(newTab()));
168 QObject::connect(ui->actionToolbarNew, SIGNAL(triggered()),
169 this, SLOT(newTab()));
171 QObject::connect(ui->actionClose_Document, SIGNAL(triggered()),
172 this, SLOT(closeCurrent()));
174 QObject::connect(ui->actionSave_Document, SIGNAL(triggered()),
175 this, SLOT(saveCurrent()));
176 QObject::connect(ui->actionSave_Document_As, SIGNAL(triggered()),
177 this, SLOT(saveCurrentAs()));
178 QObject::connect(ui->actionToolbarSave, SIGNAL(triggered()),
179 this, SLOT(saveCurrent()));
181 QObject::connect(ui->actionOpen_Document, SIGNAL(triggered()),
182 this, SLOT(openFile()));
183 QObject::connect(ui->actionToolbarOpen, SIGNAL(triggered()),
184 this, SLOT(openFile()));
186 QObject::connect(ui->actionOpen_Project, SIGNAL(triggered()),
187 this, SLOT(openProject()));
190 void EditorWindow::addTab(TabContent *doc)
192 ui->editorTabs->addTab(doc, doc->title());
194 /* Connecting to title change events */
195 QObject::connect(doc, SIGNAL(titleChanged(QString)),
196 this, SLOT(tabTitleChanged(QString)));
197 QObject::connect(doc, SIGNAL(lineChanged(int)),
198 this, SLOT(lineChanged(int)));
200 /* Connecting to settings change events */
201 if(doc->type() == TabContent::Skin)
202 dynamic_cast<SkinDocument*>(doc)->connectPrefs(prefs);
206 void EditorWindow::newTab()
208 SkinDocument* doc = new SkinDocument(parseStatus, project);
209 addTab(doc);
210 ui->editorTabs->setCurrentWidget(doc);
213 void EditorWindow::shiftTab(int index)
215 TabContent* widget = dynamic_cast<TabContent*>
216 (ui->editorTabs->currentWidget());
217 if(index < 0)
219 ui->parseTree->setModel(0);
220 ui->actionSave_Document->setEnabled(false);
221 ui->actionSave_Document_As->setEnabled(false);
222 ui->actionClose_Document->setEnabled(false);
223 ui->actionToolbarSave->setEnabled(false);
224 ui->fromTree->setEnabled(false);
225 viewer->setScene(0);
227 else if(widget->type() == TabContent::Config)
229 ui->actionSave_Document->setEnabled(true);
230 ui->actionSave_Document_As->setEnabled(true);
231 ui->actionClose_Document->setEnabled(true);
232 ui->actionToolbarSave->setEnabled(true);
233 viewer->setScene(0);
235 else if(widget->type() == TabContent::Skin)
237 /* Syncing the tree view and the status bar */
238 SkinDocument* doc = dynamic_cast<SkinDocument*>(widget);
239 ui->parseTree->setModel(doc->getModel());
240 parseStatus->setText(doc->getStatus());
242 ui->actionSave_Document->setEnabled(true);
243 ui->actionSave_Document_As->setEnabled(true);
244 ui->actionClose_Document->setEnabled(true);
245 ui->actionToolbarSave->setEnabled(true);
246 ui->fromTree->setEnabled(true);
248 sizeColumns();
250 /* Syncing the preview */
251 viewer->setScene(doc->scene());
256 bool EditorWindow::closeTab(int index)
258 TabContent* widget = dynamic_cast<TabContent*>
259 (ui->editorTabs->widget(index));
260 if(widget->requestClose())
262 ui->editorTabs->removeTab(index);
263 widget->deleteLater();
264 return true;
267 return false;
270 void EditorWindow::closeCurrent()
272 closeTab(ui->editorTabs->currentIndex());
275 void EditorWindow::saveCurrent()
277 if(ui->editorTabs->currentIndex() >= 0)
278 dynamic_cast<TabContent*>(ui->editorTabs->currentWidget())->save();
281 void EditorWindow::saveCurrentAs()
283 if(ui->editorTabs->currentIndex() >= 0)
284 dynamic_cast<TabContent*>(ui->editorTabs->currentWidget())->saveAs();
287 void EditorWindow::openFile()
289 QStringList fileNames;
290 QSettings settings;
292 settings.beginGroup("SkinDocument");
293 QString directory = settings.value("defaultDirectory", "").toString();
294 fileNames = QFileDialog::getOpenFileNames(this, tr("Open Files"), directory,
295 SkinDocument::fileFilter());
297 for(int i = 0; i < fileNames.count(); i++)
299 if(!QFile::exists(fileNames[i]))
300 continue;
302 QString current = fileNames[i];
304 loadTabFromSkinFile(current);
306 /* And setting the new default directory */
307 current.chop(current.length() - current.lastIndexOf('/') - 1);
308 settings.setValue("defaultDirectory", current);
312 settings.endGroup();
315 void EditorWindow::openProject()
317 QString fileName;
318 QSettings settings;
320 settings.beginGroup("ProjectModel");
321 QString directory = settings.value("defaultDirectory", "").toString();
322 fileName = QFileDialog::getOpenFileName(this, tr("Open Project"), directory,
323 ProjectModel::fileFilter());
325 if(QFile::exists(fileName))
328 if(project)
329 delete project;
331 project = new ProjectModel(fileName, this);
332 ui->projectTree->setModel(project);
334 QObject::connect(ui->projectTree, SIGNAL(activated(QModelIndex)),
335 project, SLOT(activated(QModelIndex)));
337 fileName.chop(fileName.length() - fileName.lastIndexOf('/') - 1);
338 settings.setValue("defaultDirectory", fileName);
340 for(int i = 0; i < ui->editorTabs->count(); i++)
342 TabContent* doc = dynamic_cast<TabContent*>
343 (ui->editorTabs->widget(i));
344 if(doc->type() == TabContent::Skin)
346 dynamic_cast<SkinDocument*>(doc)->setProject(project);
347 if(i == ui->editorTabs->currentIndex())
349 viewer->setScene(dynamic_cast<SkinDocument*>(doc)->scene());
356 settings.endGroup();
360 void EditorWindow::configFileChanged(QString configFile)
363 if(QFile::exists(configFile))
366 if(project)
367 delete project;
369 project = new ProjectModel(configFile, this);
370 ui->projectTree->setModel(project);
372 QObject::connect(ui->projectTree, SIGNAL(activated(QModelIndex)),
373 project, SLOT(activated(QModelIndex)));
375 for(int i = 0; i < ui->editorTabs->count(); i++)
377 TabContent* doc = dynamic_cast<TabContent*>
378 (ui->editorTabs->widget(i));
379 if(doc->type() == TabContent::Skin)
381 dynamic_cast<SkinDocument*>(doc)->setProject(project);
382 if(i == ui->editorTabs->currentIndex())
384 viewer->setScene(dynamic_cast<SkinDocument*>(doc)->scene());
394 void EditorWindow::tabTitleChanged(QString title)
396 TabContent* sender = dynamic_cast<TabContent*>(QObject::sender());
397 ui->editorTabs->setTabText(ui->editorTabs->indexOf(sender), title);
400 void EditorWindow::showPanel()
402 if(sender() == ui->actionFile_Panel)
403 ui->projectDock->setVisible(true);
404 if(sender() == ui->actionPreview_Panel)
405 ui->skinPreviewDock->setVisible(true);
406 if(sender() == ui->actionDisplay_Panel)
407 ui->parseTreeDock->setVisible(true);
410 void EditorWindow::closeEvent(QCloseEvent* event)
413 saveSettings();
415 /* Closing all the tabs */
416 for(int i = 0; i < ui->editorTabs->count(); i++)
418 if(!dynamic_cast<TabContent*>
419 (ui->editorTabs->widget(i))->requestClose())
421 event->ignore();
422 return;
426 event->accept();
429 void EditorWindow::updateCurrent()
431 if(ui->editorTabs->currentIndex() < 0)
432 return;
434 dynamic_cast<SkinDocument*>
435 (ui->editorTabs->currentWidget())->genCode();
438 void EditorWindow::lineChanged(int line)
440 ui->parseTree->collapseAll();
441 if(parseTreeSelection)
442 parseTreeSelection->deleteLater();
443 ParseTreeModel* model = dynamic_cast<ParseTreeModel*>
444 (ui->parseTree->model());
445 parseTreeSelection = new QItemSelectionModel(model);
446 expandLine(model, QModelIndex(), line);
447 sizeColumns();
448 ui->parseTree->setSelectionModel(parseTreeSelection);
452 void EditorWindow::expandLine(ParseTreeModel* model, QModelIndex parent,
453 int line)
455 for(int i = 0; i < model->rowCount(parent); i++)
457 QModelIndex dataType = model->index(i, ParseTreeModel::typeColumn,
458 parent);
459 QModelIndex dataVal = model->index(i, ParseTreeModel::valueColumn,
460 parent);
461 QModelIndex data = model->index(i, ParseTreeModel::lineColumn, parent);
462 QModelIndex recurse = model->index(i, 0, parent);
464 expandLine(model, recurse, line);
466 if(model->data(data, Qt::DisplayRole) == line)
468 ui->parseTree->expand(parent);
469 ui->parseTree->expand(data);
470 ui->parseTree->scrollTo(parent, QAbstractItemView::PositionAtTop);
472 parseTreeSelection->select(data, QItemSelectionModel::Select);
473 parseTreeSelection->select(dataType, QItemSelectionModel::Select);
474 parseTreeSelection->select(dataVal, QItemSelectionModel::Select);
480 void EditorWindow::sizeColumns()
482 /* Setting the column widths */
483 ui->parseTree->resizeColumnToContents(ParseTreeModel::lineColumn);
484 ui->parseTree->resizeColumnToContents(ParseTreeModel::typeColumn);
485 ui->parseTree->resizeColumnToContents(ParseTreeModel::valueColumn);
488 EditorWindow::~EditorWindow()
490 delete ui;
491 delete prefs;
492 if(project)
493 delete project;