Theme Editor: Made the device configuration menu dockable
[kugel-rb.git] / utils / themeeditor / gui / editorwindow.cpp
blob94e744e957712f4315a76af8c4e4fea30f1258ba
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), ui(new Ui::EditorWindow), parseTreeSelection(0)
35 ui->setupUi(this);
36 prefs = new PreferencesDialog(this);
37 project = 0;
38 setupUI();
39 loadSettings();
40 setupMenus();
44 EditorWindow::~EditorWindow()
46 delete ui;
47 delete prefs;
48 if(project)
49 delete project;
50 delete deviceConfig;
51 delete deviceDock;
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);
64 return;
68 /* Adding a new document*/
69 SkinDocument* doc = new SkinDocument(parseStatus, fileName, project);
70 addTab(doc);
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);
84 doc->deleteLater();
85 return;
89 addTab(doc);
90 ui->editorTabs->setCurrentWidget(doc);
92 QObject::connect(doc, SIGNAL(titleChanged(QString)),
93 this, SLOT(tabTitleChanged(QString)));
96 void EditorWindow::loadSettings()
99 QSettings settings;
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();
106 settings.endGroup();
108 if(!(size.isNull() || pos.isNull() || state.isNull()))
110 resize(size);
111 move(pos);
112 restoreState(state);
117 void EditorWindow::saveSettings()
120 QSettings settings;
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());
127 settings.endGroup();
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);
164 deviceDock->hide();
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);
223 addTab(doc);
224 ui->editorTabs->setCurrentWidget(doc);
227 void EditorWindow::shiftTab(int index)
229 TabContent* widget = dynamic_cast<TabContent*>
230 (ui->editorTabs->currentWidget());
231 if(index < 0)
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);
239 viewer->setScene(0);
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);
247 viewer->setScene(0);
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);
262 sizeColumns();
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();
278 return true;
281 return false;
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;
304 QSettings settings;
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]))
314 continue;
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);
326 settings.endGroup();
329 void EditorWindow::openProject()
331 QString fileName;
332 QSettings settings;
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))
342 if(project)
343 delete project;
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());
370 settings.endGroup();
374 void EditorWindow::configFileChanged(QString configFile)
377 if(QFile::exists(configFile))
380 if(project)
381 delete project;
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)
427 saveSettings();
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())
435 event->ignore();
436 return;
440 event->accept();
443 void EditorWindow::updateCurrent()
445 if(ui->editorTabs->currentIndex() < 0)
446 return;
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);
459 sizeColumns();
460 ui->parseTree->setSelectionModel(parseTreeSelection);
464 void EditorWindow::expandLine(ParseTreeModel* model, QModelIndex parent,
465 int line)
467 for(int i = 0; i < model->rowCount(parent); i++)
469 QModelIndex dataType = model->index(i, ParseTreeModel::typeColumn,
470 parent);
471 QModelIndex dataVal = model->index(i, ParseTreeModel::valueColumn,
472 parent);
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);