From ca564287ee3f48945d45c7d92be7a83452f53745 Mon Sep 17 00:00:00 2001 From: Robert Bieber Date: Thu, 17 Jun 2010 05:37:01 +0000 Subject: Theme Editor: Moved source files into subdirectories git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26876 a1c6a512-1295-4272-9138-f99709370657 --- utils/themeeditor/gui/codeeditor.cpp | 149 +++++++++ utils/themeeditor/gui/codeeditor.h | 106 +++++++ utils/themeeditor/gui/configdocument.cpp | 267 ++++++++++++++++ utils/themeeditor/gui/configdocument.h | 86 +++++ utils/themeeditor/gui/configdocument.ui | 79 +++++ utils/themeeditor/gui/editorwindow.cpp | 468 ++++++++++++++++++++++++++++ utils/themeeditor/gui/editorwindow.h | 93 ++++++ utils/themeeditor/gui/editorwindow.ui | 324 +++++++++++++++++++ utils/themeeditor/gui/preferencesdialog.cpp | 206 ++++++++++++ utils/themeeditor/gui/preferencesdialog.h | 72 +++++ utils/themeeditor/gui/preferencesdialog.ui | 306 ++++++++++++++++++ utils/themeeditor/gui/skindocument.cpp | 311 ++++++++++++++++++ utils/themeeditor/gui/skindocument.h | 96 ++++++ utils/themeeditor/gui/skinhighlighter.cpp | 172 ++++++++++ utils/themeeditor/gui/skinhighlighter.h | 59 ++++ utils/themeeditor/gui/skinviewer.cpp | 67 ++++ utils/themeeditor/gui/skinviewer.h | 51 +++ utils/themeeditor/gui/skinviewer.ui | 42 +++ utils/themeeditor/gui/tabcontent.h | 35 +++ 19 files changed, 2989 insertions(+) create mode 100644 utils/themeeditor/gui/codeeditor.cpp create mode 100644 utils/themeeditor/gui/codeeditor.h create mode 100644 utils/themeeditor/gui/configdocument.cpp create mode 100644 utils/themeeditor/gui/configdocument.h create mode 100644 utils/themeeditor/gui/configdocument.ui create mode 100644 utils/themeeditor/gui/editorwindow.cpp create mode 100644 utils/themeeditor/gui/editorwindow.h create mode 100644 utils/themeeditor/gui/editorwindow.ui create mode 100644 utils/themeeditor/gui/preferencesdialog.cpp create mode 100644 utils/themeeditor/gui/preferencesdialog.h create mode 100644 utils/themeeditor/gui/preferencesdialog.ui create mode 100644 utils/themeeditor/gui/skindocument.cpp create mode 100644 utils/themeeditor/gui/skindocument.h create mode 100644 utils/themeeditor/gui/skinhighlighter.cpp create mode 100644 utils/themeeditor/gui/skinhighlighter.h create mode 100644 utils/themeeditor/gui/skinviewer.cpp create mode 100644 utils/themeeditor/gui/skinviewer.h create mode 100644 utils/themeeditor/gui/skinviewer.ui create mode 100644 utils/themeeditor/gui/tabcontent.h (limited to 'utils/themeeditor/gui') diff --git a/utils/themeeditor/gui/codeeditor.cpp b/utils/themeeditor/gui/codeeditor.cpp new file mode 100644 index 0000000..49f4410 --- /dev/null +++ b/utils/themeeditor/gui/codeeditor.cpp @@ -0,0 +1,149 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * This file has been copied from Nokia's Qt Examples, with minor modifications + * made available under the LGPL version 2.1, as the original file was licensed + * + **************************************************************************** + **************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include + +#include "codeeditor.h" + +//![constructor] + +CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent) +{ + lineNumberArea = new LineNumberArea(this); + + connect(this, SIGNAL(blockCountChanged(int)), + this, SLOT(updateLineNumberAreaWidth(int))); + connect(this, SIGNAL(updateRequest(QRect,int)), + this, SLOT(updateLineNumberArea(QRect,int))); + + updateLineNumberAreaWidth(0); +} + +//![constructor] + +//![extraAreaWidth] + +int CodeEditor::lineNumberAreaWidth() +{ + int digits = 1; + int max = qMax(1, blockCount()); + while (max >= 10) { + max /= 10; + ++digits; + } + + int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits; + + return space; +} + +//![extraAreaWidth] + +//![slotUpdateExtraAreaWidth] + +void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */) +{ + setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); +} + +//![slotUpdateExtraAreaWidth] + +//![slotUpdateRequest] + +void CodeEditor::updateLineNumberArea(const QRect &rect, int dy) +{ + if (dy) + lineNumberArea->scroll(0, dy); + else + lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); + + if (rect.contains(viewport()->rect())) + updateLineNumberAreaWidth(0); +} + +//![slotUpdateRequest] + +//![resizeEvent] + +void CodeEditor::resizeEvent(QResizeEvent *e) +{ + QPlainTextEdit::resizeEvent(e); + + QRect cr = contentsRect(); + lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), + lineNumberAreaWidth(), cr.height())); +} + +//![resizeEvent] + +//![extraAreaPaintEvent_0] + +void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event) +{ + QPainter painter(lineNumberArea); + painter.fillRect(event->rect(), Qt::lightGray); + +//![extraAreaPaintEvent_0] + +//![extraAreaPaintEvent_1] + QTextBlock block = firstVisibleBlock(); + int blockNumber = block.blockNumber(); + int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top(); + int bottom = top + (int) blockBoundingRect(block).height(); +//![extraAreaPaintEvent_1] + +//![extraAreaPaintEvent_2] + while (block.isValid() && top <= event->rect().bottom()) { + if (block.isVisible() && bottom >= event->rect().top()) { + QString number = QString::number(blockNumber + 1); + /* Drawing an error circle if necessary */ + if(errors.contains(blockNumber + 1)) + { + painter.fillRect(QRect(0, top, lineNumberArea->width(), + fontMetrics().height()), errorColor); + } + painter.setPen(Qt::black); + painter.drawText(0, top, lineNumberArea->width(), + fontMetrics().height(), Qt::AlignRight, number); + } + + block = block.next(); + top = bottom; + bottom = top + (int) blockBoundingRect(block).height(); + ++blockNumber; + } +} +//![extraAreaPaintEvent_2] + diff --git a/utils/themeeditor/gui/codeeditor.h b/utils/themeeditor/gui/codeeditor.h new file mode 100644 index 0000000..1771e31 --- /dev/null +++ b/utils/themeeditor/gui/codeeditor.h @@ -0,0 +1,106 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * This file has been copied from Nokia's Qt Examples, with minor modifications + * made available under the LGPL version 2.1, as the original file was licensed + * + **************************************************************************** + **************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CODEEDITOR_H +#define CODEEDITOR_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QPaintEvent; +class QResizeEvent; +class QSize; +class QWidget; +QT_END_NAMESPACE + +class LineNumberArea; + +//![codeeditordefinition] + +class CodeEditor : public QPlainTextEdit +{ + Q_OBJECT + +public: + CodeEditor(QWidget *parent = 0); + + void lineNumberAreaPaintEvent(QPaintEvent *event); + int lineNumberAreaWidth(); + void addError(int line){ errors.append(line); } + void clearErrors(){ errors.clear(); } + void setErrorColor(QColor color){ errorColor = color; } + bool isError(int line){ return errors.contains(line); } + bool hasErrors(){ return !errors.isEmpty(); } + +protected: + void resizeEvent(QResizeEvent *event); + +private slots: + void updateLineNumberAreaWidth(int newBlockCount); + void updateLineNumberArea(const QRect &, int); + +private: + QWidget *lineNumberArea; + QList errors; + QColor errorColor; +}; + +//![codeeditordefinition] +//![extraarea] + +class LineNumberArea : public QWidget +{ +public: + LineNumberArea(CodeEditor *editor) : QWidget(editor) { + codeEditor = editor; + } + + QSize sizeHint() const { + return QSize(codeEditor->lineNumberAreaWidth(), 0); + } + +protected: + void paintEvent(QPaintEvent *event) { + codeEditor->lineNumberAreaPaintEvent(event); + } + +private: + CodeEditor *codeEditor; +}; + +//![extraarea] + +#endif diff --git a/utils/themeeditor/gui/configdocument.cpp b/utils/themeeditor/gui/configdocument.cpp new file mode 100644 index 0000000..a897d3b --- /dev/null +++ b/utils/themeeditor/gui/configdocument.cpp @@ -0,0 +1,267 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "projectmodel.h" +#include "configdocument.h" +#include "ui_configdocument.h" + +#include +#include +#include +#include + +ConfigDocument::ConfigDocument(QMap& settings, QString file, + QWidget *parent) + : TabContent(parent), + ui(new Ui::ConfigDocument), + filePath(file) +{ + ui->setupUi(this); + + /* Populating the known keys list */ + QFile fin(":/resources/configkeys"); + fin.open(QFile::ReadOnly); + + QStringList* container = &primaryKeys; + while(!fin.atEnd()) + { + QString current = QString(fin.readLine()); + if(current == "-\n") + container = &secondaryKeys; + else if(current != "\n") + container->append(current.trimmed()); + } + + QMap::iterator i; + for(i = settings.begin(); i != settings.end(); i++) + if(i.key() != "themebase") + addRow(i.key(), i.value()); + + saved = toPlainText(); + + QObject::connect(ui->addKeyButton, SIGNAL(pressed()), + this, SLOT(addClicked())); +} + +ConfigDocument::~ConfigDocument() +{ + delete ui; +} + +void ConfigDocument::changeEvent(QEvent *e) +{ + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + +QString ConfigDocument::title() const +{ + QStringList decompose = filePath.split("/"); + return decompose.last(); +} + +void ConfigDocument::save() +{ + QFile fout(filePath); + + if(!fout.exists()) + { + saveAs(); + return; + } + + fout.open(QFile::WriteOnly); + fout.write(toPlainText().toAscii()); + fout.close(); + + saved = toPlainText(); + emit titleChanged(title()); + +} + +void ConfigDocument::saveAs() +{ + /* Determining the directory to open */ + QString directory = filePath; + + QSettings settings; + settings.beginGroup("ProjectModel"); + if(directory == "") + directory = settings.value("defaultDirectory", "").toString(); + + filePath = QFileDialog::getSaveFileName(this, tr("Save Document"), + directory, + ProjectModel::fileFilter()); + directory = filePath; + if(filePath == "") + return; + + directory.chop(filePath.length() - filePath.lastIndexOf('/') - 1); + settings.setValue("defaultDirectory", directory); + settings.endGroup(); + + QFile fout(filePath); + fout.open(QFile::WriteOnly); + fout.write(toPlainText().toAscii()); + fout.close(); + + saved = toPlainText(); + emit titleChanged(title()); + emit configFileChanged(file()); + +} + +bool ConfigDocument::requestClose() +{ + if(toPlainText() != saved) + { + /* Spawning the "Are you sure?" dialog */ + QMessageBox confirm(this); + confirm.setWindowTitle(tr("Confirm Close")); + confirm.setText(title() + tr(" has been modified.")); + confirm.setInformativeText(tr("Do you want to save your changes?")); + confirm.setStandardButtons(QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + confirm.setDefaultButton(QMessageBox::Save); + int confirmation = confirm.exec(); + + switch(confirmation) + { + case QMessageBox::Save: + save(); + /* After calling save, make sure the user actually went through */ + if(toPlainText() != saved) + return false; + else + return true; + + case QMessageBox::Discard: + return true; + + case QMessageBox::Cancel: + return false; + } + } + return true; +} + +QString ConfigDocument::toPlainText() const +{ + QString buffer = ""; + + for(int i = 0; i < keys.count(); i++) + { + buffer += keys[i]->currentText(); + buffer += ":"; + buffer += values[i]->text(); + buffer += "\n"; + } + + return buffer; +} + +void ConfigDocument::addRow(QString key, QString value) +{ + QHBoxLayout* layout = new QHBoxLayout(); + QComboBox* keyEdit = new QComboBox(this); + QLineEdit* valueEdit = new QLineEdit(value, this); + QPushButton* delButton = new QPushButton(tr("-"), this); + QLabel* label = new QLabel(":"); + + /* Loading the combo box options */ + keyEdit->setInsertPolicy(QComboBox::InsertAlphabetically); + keyEdit->setEditable(true); + keyEdit->addItems(primaryKeys); + keyEdit->insertSeparator(keyEdit->count()); + keyEdit->addItems(secondaryKeys); + if(keyEdit->findText(key) != -1) + keyEdit->setCurrentIndex(keyEdit->findText(key)); + else + keyEdit->setEditText(key); + + layout->addWidget(keyEdit); + layout->addWidget(label); + layout->addWidget(valueEdit); + layout->addWidget(delButton); + + delButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); + delButton->setMaximumWidth(35); + + QObject::connect(delButton, SIGNAL(clicked()), + this, SLOT(deleteClicked())); + QObject::connect(keyEdit, SIGNAL(currentIndexChanged(QString)), + this, SLOT(textChanged())); + QObject::connect(keyEdit, SIGNAL(textChanged(QString)), + this, SLOT(textChanged())); + QObject::connect(valueEdit, SIGNAL(textChanged(QString)), + this, SLOT(textChanged())); + + ui->configBoxes->addLayout(layout); + + containers.append(layout); + keys.append(keyEdit); + values.append(valueEdit); + deleteButtons.append(delButton); + labels.append(label); + +} + +void ConfigDocument::deleteClicked() +{ + QPushButton* button = dynamic_cast(sender()); + int row = deleteButtons.indexOf(button); + + deleteButtons[row]->deleteLater(); + keys[row]->deleteLater(); + values[row]->deleteLater(); + containers[row]->deleteLater(); + labels[row]->deleteLater(); + + deleteButtons.removeAt(row); + keys.removeAt(row); + values.removeAt(row); + containers.removeAt(row); + labels.removeAt(row); + + if(saved != toPlainText()) + emit titleChanged(title() + "*"); + else + emit titleChanged(title()); +} + +void ConfigDocument::addClicked() +{ + addRow(tr("Key"), tr("Value")); +} + +void ConfigDocument::textChanged() +{ + if(toPlainText() != saved) + emit titleChanged(title() + "*"); + else + emit titleChanged(title()); +} diff --git a/utils/themeeditor/gui/configdocument.h b/utils/themeeditor/gui/configdocument.h new file mode 100644 index 0000000..8493c7a --- /dev/null +++ b/utils/themeeditor/gui/configdocument.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef CONFIGDOCUMENT_H +#define CONFIGDOCUMENT_H + +#include +#include +#include +#include +#include +#include +#include + +#include "tabcontent.h" + +namespace Ui { + class ConfigDocument; +} + +class ConfigDocument : public TabContent { + Q_OBJECT +public: + ConfigDocument(QMap& settings, QString file, + QWidget *parent = 0); + virtual ~ConfigDocument(); + + TabType type() const{ return TabContent::Config; } + QString file() const{ return filePath; } + QString title() const; + + QString toPlainText() const; + + void save(); + void saveAs(); + + bool requestClose(); + +protected: + void changeEvent(QEvent *e); + +signals: + void configFileChanged(QString); + +private slots: + void deleteClicked(); + void addClicked(); + void textChanged(); + + +private: + Ui::ConfigDocument *ui; + QList containers; + QList keys; + QList values; + QList deleteButtons; + QList labels; + + QStringList primaryKeys; + QStringList secondaryKeys; + + QString filePath; + QString saved; + + void addRow(QString key, QString value); +}; + +#endif // CONFIGDOCUMENT_H diff --git a/utils/themeeditor/gui/configdocument.ui b/utils/themeeditor/gui/configdocument.ui new file mode 100644 index 0000000..e2f9e7f --- /dev/null +++ b/utils/themeeditor/gui/configdocument.ui @@ -0,0 +1,79 @@ + + + ConfigDocument + + + + 0 + 0 + 422 + 299 + + + + Form + + + + + + true + + + + + 0 + 0 + 402 + 244 + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 35 + 16777215 + + + + + + + + + + + + + + + diff --git a/utils/themeeditor/gui/editorwindow.cpp b/utils/themeeditor/gui/editorwindow.cpp new file mode 100644 index 0000000..675520d --- /dev/null +++ b/utils/themeeditor/gui/editorwindow.cpp @@ -0,0 +1,468 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "editorwindow.h" +#include "projectmodel.h" +#include "ui_editorwindow.h" + +#include +#include +#include +#include +#include + +EditorWindow::EditorWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::EditorWindow) +{ + ui->setupUi(this); + prefs = new PreferencesDialog(this); + project = 0; + loadSettings(); + setupUI(); + setupMenus(); +} + +void EditorWindow::loadTabFromSkinFile(QString fileName) +{ + /* Checking to see if the file is already open */ + for(int i = 0; i < ui->editorTabs->count(); i++) + { + TabContent* current = dynamic_cast + (ui->editorTabs->widget(i)); + if(current->file() == fileName) + { + ui->editorTabs->setCurrentIndex(i); + return; + } + } + + /* Adding a new document*/ + SkinDocument* doc = new SkinDocument(parseStatus, fileName); + addTab(doc); + ui->editorTabs->setCurrentWidget(doc); + +} + +void EditorWindow::loadConfigTab(ConfigDocument* doc) +{ + for(int i = 0; i < ui->editorTabs->count(); i++) + { + TabContent* current = dynamic_cast + (ui->editorTabs->widget(i)); + if(current->file() == doc->file()) + { + ui->editorTabs->setCurrentIndex(i); + doc->deleteLater(); + return; + } + } + + addTab(doc); + ui->editorTabs->setCurrentWidget(doc); + + QObject::connect(doc, SIGNAL(titleChanged(QString)), + this, SLOT(tabTitleChanged(QString))); +} + +void EditorWindow::loadSettings() +{ + + QSettings settings; + + /* Main Window location */ + settings.beginGroup("EditorWindow"); + QSize size = settings.value("size").toSize(); + QPoint pos = settings.value("position").toPoint(); + QByteArray state = settings.value("state").toByteArray(); + settings.endGroup(); + + if(!(size.isNull() || pos.isNull() || state.isNull())) + { + resize(size); + move(pos); + restoreState(state); + } + +} + +void EditorWindow::saveSettings() +{ + + QSettings settings; + + /* Saving window and panel positions */ + settings.beginGroup("EditorWindow"); + settings.setValue("position", pos()); + settings.setValue("size", size()); + settings.setValue("state", saveState()); + settings.endGroup(); +} + +void EditorWindow::setupUI() +{ + /* Connecting the tab bar signals */ + QObject::connect(ui->editorTabs, SIGNAL(currentChanged(int)), + this, SLOT(shiftTab(int))); + QObject::connect(ui->editorTabs, SIGNAL(tabCloseRequested(int)), + this, SLOT(closeTab(int))); + + /* Connecting the code gen button */ + QObject::connect(ui->fromTree, SIGNAL(pressed()), + this, SLOT(updateCurrent())); + + /* Connecting the preferences dialog */ + QObject::connect(ui->actionPreferences, SIGNAL(triggered()), + prefs, SLOT(exec())); + + /* Setting up the parse status label */ + parseStatus = new QLabel(this); + ui->statusbar->addPermanentWidget(parseStatus); + + /* Setting the selection for parse tree highlighting initially NULL */ + parseTreeSelection = 0; + + /* Adding the skin viewer */ + viewer = new SkinViewer(this); + ui->skinPreviewLayout->addWidget(viewer); + + //TODO: Remove this test code + QGraphicsScene* test = new QGraphicsScene(); + test->addRect(0,0,50,50); + + viewer->setScene(test); +} + +void EditorWindow::setupMenus() +{ + /* Connecting panel show actions */ + QObject::connect(ui->actionFile_Panel, SIGNAL(triggered()), + this, SLOT(showPanel())); + QObject::connect(ui->actionDisplay_Panel, SIGNAL(triggered()), + this, SLOT(showPanel())); + QObject::connect(ui->actionPreview_Panel, SIGNAL(triggered()), + this, SLOT(showPanel())); + + /* Connecting the document management actions */ + QObject::connect(ui->actionNew_Document, SIGNAL(triggered()), + this, SLOT(newTab())); + QObject::connect(ui->actionToolbarNew, SIGNAL(triggered()), + this, SLOT(newTab())); + + QObject::connect(ui->actionClose_Document, SIGNAL(triggered()), + this, SLOT(closeCurrent())); + + QObject::connect(ui->actionSave_Document, SIGNAL(triggered()), + this, SLOT(saveCurrent())); + QObject::connect(ui->actionSave_Document_As, SIGNAL(triggered()), + this, SLOT(saveCurrentAs())); + QObject::connect(ui->actionToolbarSave, SIGNAL(triggered()), + this, SLOT(saveCurrent())); + + QObject::connect(ui->actionOpen_Document, SIGNAL(triggered()), + this, SLOT(openFile())); + QObject::connect(ui->actionToolbarOpen, SIGNAL(triggered()), + this, SLOT(openFile())); + + QObject::connect(ui->actionOpen_Project, SIGNAL(triggered()), + this, SLOT(openProject())); +} + +void EditorWindow::addTab(TabContent *doc) +{ + ui->editorTabs->addTab(doc, doc->title()); + + /* Connecting to title change events */ + QObject::connect(doc, SIGNAL(titleChanged(QString)), + this, SLOT(tabTitleChanged(QString))); + QObject::connect(doc, SIGNAL(lineChanged(int)), + this, SLOT(lineChanged(int))); + + /* Connecting to settings change events */ + if(doc->type() == TabContent::Skin) + dynamic_cast(doc)->connectPrefs(prefs); +} + + +void EditorWindow::newTab() +{ + SkinDocument* doc = new SkinDocument(parseStatus); + addTab(doc); + ui->editorTabs->setCurrentWidget(doc); +} + +void EditorWindow::shiftTab(int index) +{ + TabContent* widget = dynamic_cast + (ui->editorTabs->currentWidget()); + if(index < 0) + { + ui->parseTree->setModel(0); + ui->actionSave_Document->setEnabled(false); + ui->actionSave_Document_As->setEnabled(false); + ui->actionClose_Document->setEnabled(false); + ui->actionToolbarSave->setEnabled(false); + ui->fromTree->setEnabled(false); + } + else if(widget->type() == TabContent::Config) + { + ui->actionSave_Document->setEnabled(true); + ui->actionSave_Document_As->setEnabled(true); + ui->actionClose_Document->setEnabled(true); + ui->actionToolbarSave->setEnabled(true); + } + else + { + /* Syncing the tree view and the status bar */ + SkinDocument* doc = dynamic_cast(widget); + ui->parseTree->setModel(doc->getModel()); + parseStatus->setText(doc->getStatus()); + + ui->actionSave_Document->setEnabled(true); + ui->actionSave_Document_As->setEnabled(true); + ui->actionClose_Document->setEnabled(true); + ui->actionToolbarSave->setEnabled(true); + ui->fromTree->setEnabled(true); + + sizeColumns(); + + } +} + +bool EditorWindow::closeTab(int index) +{ + TabContent* widget = dynamic_cast + (ui->editorTabs->widget(index)); + if(widget->requestClose()) + { + ui->editorTabs->removeTab(index); + widget->deleteLater(); + return true; + } + + return false; +} + +void EditorWindow::closeCurrent() +{ + closeTab(ui->editorTabs->currentIndex()); +} + +void EditorWindow::saveCurrent() +{ + if(ui->editorTabs->currentIndex() >= 0) + dynamic_cast(ui->editorTabs->currentWidget())->save(); +} + +void EditorWindow::saveCurrentAs() +{ + if(ui->editorTabs->currentIndex() >= 0) + dynamic_cast(ui->editorTabs->currentWidget())->saveAs(); +} + +void EditorWindow::openFile() +{ + QStringList fileNames; + QSettings settings; + + settings.beginGroup("SkinDocument"); + QString directory = settings.value("defaultDirectory", "").toString(); + fileNames = QFileDialog::getOpenFileNames(this, tr("Open Files"), directory, + SkinDocument::fileFilter()); + + for(int i = 0; i < fileNames.count(); i++) + { + if(!QFile::exists(fileNames[i])) + continue; + + QString current = fileNames[i]; + + loadTabFromSkinFile(current); + + /* And setting the new default directory */ + current.chop(current.length() - current.lastIndexOf('/') - 1); + settings.setValue("defaultDirectory", current); + + } + + settings.endGroup(); +} + +void EditorWindow::openProject() +{ + QString fileName; + QSettings settings; + + settings.beginGroup("ProjectModel"); + QString directory = settings.value("defaultDirectory", "").toString(); + fileName = QFileDialog::getOpenFileName(this, tr("Open Project"), directory, + ProjectModel::fileFilter()); + + if(QFile::exists(fileName)) + { + + if(project) + delete project; + + project = new ProjectModel(fileName, this); + ui->projectTree->setModel(project); + + QObject::connect(ui->projectTree, SIGNAL(activated(QModelIndex)), + project, SLOT(activated(QModelIndex))); + + fileName.chop(fileName.length() - fileName.lastIndexOf('/') - 1); + settings.setValue("defaultDirectory", fileName); + + } + + settings.endGroup(); + +} + +void EditorWindow::configFileChanged(QString configFile) +{ + + QSettings settings; + + settings.beginGroup("ProjectModel"); + + if(QFile::exists(configFile)) + { + + if(project) + delete project; + + project = new ProjectModel(configFile, this); + ui->projectTree->setModel(project); + + QObject::connect(ui->projectTree, SIGNAL(activated(QModelIndex)), + project, SLOT(activated(QModelIndex))); + + configFile.chop(configFile.length() - configFile.lastIndexOf('/') - 1); + settings.setValue("defaultDirectory", configFile); + + } + + settings.endGroup(); + +} + +void EditorWindow::tabTitleChanged(QString title) +{ + TabContent* sender = dynamic_cast(QObject::sender()); + ui->editorTabs->setTabText(ui->editorTabs->indexOf(sender), title); +} + +void EditorWindow::showPanel() +{ + if(sender() == ui->actionFile_Panel) + ui->projectDock->setVisible(true); + if(sender() == ui->actionPreview_Panel) + ui->skinPreviewDock->setVisible(true); + if(sender() == ui->actionDisplay_Panel) + ui->parseTreeDock->setVisible(true); +} + +void EditorWindow::closeEvent(QCloseEvent* event) +{ + + saveSettings(); + + /* Closing all the tabs */ + for(int i = 0; i < ui->editorTabs->count(); i++) + { + if(!dynamic_cast + (ui->editorTabs->widget(i))->requestClose()) + { + event->ignore(); + return; + } + } + + event->accept(); +} + +void EditorWindow::updateCurrent() +{ + if(ui->editorTabs->currentIndex() < 0) + return; + + dynamic_cast + (ui->editorTabs->currentWidget())->genCode(); +} + +void EditorWindow::lineChanged(int line) +{ + ui->parseTree->collapseAll(); + if(parseTreeSelection) + parseTreeSelection->deleteLater(); + ParseTreeModel* model = dynamic_cast + (ui->parseTree->model()); + parseTreeSelection = new QItemSelectionModel(model); + expandLine(model, QModelIndex(), line); + sizeColumns(); + ui->parseTree->setSelectionModel(parseTreeSelection); + +} + +void EditorWindow::expandLine(ParseTreeModel* model, QModelIndex parent, + int line) +{ + for(int i = 0; i < model->rowCount(parent); i++) + { + QModelIndex dataType = model->index(i, ParseTreeModel::typeColumn, + parent); + QModelIndex dataVal = model->index(i, ParseTreeModel::valueColumn, + parent); + QModelIndex data = model->index(i, ParseTreeModel::lineColumn, parent); + QModelIndex recurse = model->index(i, 0, parent); + + expandLine(model, recurse, line); + + if(model->data(data, Qt::DisplayRole) == line) + { + ui->parseTree->expand(parent); + ui->parseTree->expand(data); + ui->parseTree->scrollTo(parent, QAbstractItemView::PositionAtTop); + + parseTreeSelection->select(data, QItemSelectionModel::Select); + parseTreeSelection->select(dataType, QItemSelectionModel::Select); + parseTreeSelection->select(dataVal, QItemSelectionModel::Select); + } + + } +} + +void EditorWindow::sizeColumns() +{ + /* Setting the column widths */ + ui->parseTree->resizeColumnToContents(ParseTreeModel::lineColumn); + ui->parseTree->resizeColumnToContents(ParseTreeModel::typeColumn); + ui->parseTree->resizeColumnToContents(ParseTreeModel::valueColumn); +} + +EditorWindow::~EditorWindow() +{ + delete ui; + delete prefs; + if(project) + delete project; +} diff --git a/utils/themeeditor/gui/editorwindow.h b/utils/themeeditor/gui/editorwindow.h new file mode 100644 index 0000000..6f73735 --- /dev/null +++ b/utils/themeeditor/gui/editorwindow.h @@ -0,0 +1,93 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef EDITORWINDOW_H +#define EDITORWINDOW_H + +#include +#include +#include + +#include "parsetreemodel.h" +#include "skinhighlighter.h" +#include "skindocument.h" +#include "configdocument.h" +#include "preferencesdialog.h" +#include "skinviewer.h" + +class ProjectModel; +class TabContent; + +namespace Ui +{ + class EditorWindow; +} + +class EditorWindow : public QMainWindow +{ + Q_OBJECT +public: + EditorWindow(QWidget *parent = 0); + ~EditorWindow(); + + /* A public function so external widgets can load files */ + void loadTabFromSkinFile(QString fileName); + void loadConfigTab(ConfigDocument* doc); + +protected: + virtual void closeEvent(QCloseEvent* event); + +public slots: + void configFileChanged(QString configFile); + +private slots: + void showPanel(); + void newTab(); + void shiftTab(int index); + bool closeTab(int index); + void closeCurrent(); + void saveCurrent(); + void saveCurrentAs(); + void openFile(); + void openProject(); + void tabTitleChanged(QString title); + void updateCurrent(); /* Generates code in the current tab */ + void lineChanged(int line); /* Used for auto-expand */ + +private: + /* Setup functions */ + void loadSettings(); + void saveSettings(); + void setupUI(); + void setupMenus(); + void addTab(TabContent* doc); + void expandLine(ParseTreeModel* model, QModelIndex parent, int line); + void sizeColumns(); + + Ui::EditorWindow *ui; + PreferencesDialog* prefs; + QLabel* parseStatus; + ProjectModel* project; + QItemSelectionModel* parseTreeSelection; + SkinViewer* viewer; +}; + +#endif // EDITORWINDOW_H diff --git a/utils/themeeditor/gui/editorwindow.ui b/utils/themeeditor/gui/editorwindow.ui new file mode 100644 index 0000000..10e2c52 --- /dev/null +++ b/utils/themeeditor/gui/editorwindow.ui @@ -0,0 +1,324 @@ + + + EditorWindow + + + + 0 + 0 + 628 + 433 + + + + Rockbox Theme Editor + + + + :/resources/resources/windowicon.png:/resources/resources/windowicon.png + + + + + + + -1 + + + true + + + true + + + + + + + + + 0 + 0 + 628 + 25 + + + + + &File + + + + + + + + + + + + + + + + + &View + + + + + + + + + + + + Skin Preview + + + 2 + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + Project + + + 1 + + + + + + + + + + + + Parse Tree + + + 2 + + + + + + + true + + + QAbstractItemView::MultiSelection + + + + + + + false + + + Update Code + + + + + + + + + &Quit + + + Ctrl+Q + + + + + false + + + false + + + Parse &Tree Panel + + + + + &Preferences + + + Ctrl+P + + + + + false + + + false + + + P&roject Panel + + + + + false + + + false + + + &Preview Panel + + + + + &New Document + + + Ctrl+N + + + + + &Open Document + + + Ctrl+O + + + + + false + + + &Save Document + + + Ctrl+S + + + + + false + + + &Close Document + + + Ctrl+W + + + + + false + + + Save Document &As + + + Ctrl+Shift+S + + + + + + :/resources/resources/document-new.png:/resources/resources/document-new.png + + + ToolbarNew + + + New + + + + + + :/resources/resources/document-open.png:/resources/resources/document-open.png + + + ToolbarOpen + + + Open + + + + + false + + + + :/resources/resources/document-save.png:/resources/resources/document-save.png + + + ToolbarSave + + + Save + + + + + Open P&roject + + + Ctrl+Shift+O + + + + + projectTree + parseTree + fromTree + editorTabs + + + + + + + actionQuit + activated() + EditorWindow + close() + + + -1 + -1 + + + 299 + 199 + + + + + diff --git a/utils/themeeditor/gui/preferencesdialog.cpp b/utils/themeeditor/gui/preferencesdialog.cpp new file mode 100644 index 0000000..8cd9665 --- /dev/null +++ b/utils/themeeditor/gui/preferencesdialog.cpp @@ -0,0 +1,206 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "preferencesdialog.h" +#include "ui_preferencesdialog.h" + +#include +#include + +PreferencesDialog::PreferencesDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::PreferencesDialog) +{ + ui->setupUi(this); + setupUI(); + loadSettings(); +} + +PreferencesDialog::~PreferencesDialog() +{ + delete ui; +} + +void PreferencesDialog::loadSettings() +{ + loadColors(); + loadFont(); +} + +void PreferencesDialog::loadColors() +{ + + QSettings settings; + + /* The list of buttons from the SkinHighlighter group */ + + settings.beginGroup("SkinHighlighter"); + + commentColor = settings.value("commentColor", + QColor(0, 180, 0)).value(); + setButtonColor(ui->commentButton, commentColor); + + escapedColor = settings.value("escapedColor", + QColor(120,120,120)).value(); + setButtonColor(ui->escapedButton, escapedColor); + + conditionalColor = settings.value("conditionalColor", + QColor(0, 0, 180)).value(); + setButtonColor(ui->conditionalButton, conditionalColor); + + tagColor = settings.value("tagColor", + QColor(180, 0, 0)).value(); + setButtonColor(ui->tagButton, tagColor); + + settings.endGroup(); + + /* Buttons from the editor group */ + settings.beginGroup("SkinDocument"); + + fgColor = settings.value("fgColor", Qt::black).value(); + setButtonColor(ui->fgButton, fgColor); + + bgColor = settings.value("bgColor", Qt::white).value(); + setButtonColor(ui->bgButton, bgColor); + + errorColor = settings.value("errorColor", Qt::red).value(); + setButtonColor(ui->errorButton, errorColor); + + settings.endGroup(); +} + +void PreferencesDialog::loadFont() +{ + QSettings settings; + settings.beginGroup("SkinDocument"); + + QFont def("Monospace"); + def.setStyleHint(QFont::TypeWriter); + + QVariant family = settings.value("fontFamily", def); + int size = settings.value("fontSize", 12).toInt(); + + settings.endGroup(); + + ui->fontSelect->setCurrentFont(family.value()); + ui->fontSize->setValue(size); + +} + +void PreferencesDialog::saveSettings() +{ + saveColors(); + saveFont(); +} + +void PreferencesDialog::saveColors() +{ + QSettings settings; + + /* Saving the editor colors */ + settings.beginGroup("SkinDocument"); + + settings.setValue("fgColor", fgColor); + settings.setValue("bgColor", bgColor); + settings.setValue("errorColor", errorColor); + + settings.endGroup(); + + /* Saving the highlighting colors */ + settings.beginGroup("SkinHighlighter"); + + settings.setValue("tagColor", tagColor); + settings.setValue("commentColor", commentColor); + settings.setValue("conditionalColor", conditionalColor); + settings.setValue("escapedColor", escapedColor); + + settings.endGroup(); +} + +void PreferencesDialog::saveFont() +{ + QSettings settings; + settings.beginGroup("SkinDocument"); + + settings.setValue("fontFamily", ui->fontSelect->currentFont()); + settings.setValue("fontSize", ui->fontSize->value()); + + settings.endGroup(); +} + +void PreferencesDialog::setupUI() +{ + /* Connecting color buttons */ + QList buttons; + buttons.append(ui->bgButton); + buttons.append(ui->fgButton); + buttons.append(ui->commentButton); + buttons.append(ui->tagButton); + buttons.append(ui->conditionalButton); + buttons.append(ui->escapedButton); + buttons.append(ui->errorButton); + + for(int i = 0; i < buttons.count(); i++) + QObject::connect(buttons[i], SIGNAL(pressed()), + this, SLOT(colorClicked())); +} + +void PreferencesDialog::colorClicked() +{ + QColor* toEdit = 0, newColor; + + if(QObject::sender() == ui->bgButton) + toEdit = &bgColor; + else if(QObject::sender() == ui->fgButton) + toEdit = &fgColor; + else if(QObject::sender() == ui->commentButton) + toEdit = &commentColor; + else if(QObject::sender() == ui->tagButton) + toEdit = &tagColor; + else if(QObject::sender() == ui->conditionalButton) + toEdit = &conditionalColor; + else if(QObject::sender() == ui->escapedButton) + toEdit = &escapedColor; + else if(QObject::sender() == ui->errorButton) + toEdit = &errorColor; + + if(!toEdit) + return; + + newColor = QColorDialog::getColor(*toEdit, this); + if (newColor.isValid()) + { + *toEdit = newColor; + setButtonColor(dynamic_cast(QObject::sender()), *toEdit); + } +} + +void PreferencesDialog::accept() +{ + saveSettings(); + QDialog::accept(); +} + +void PreferencesDialog::reject() +{ + loadSettings(); + QDialog::reject(); +} diff --git a/utils/themeeditor/gui/preferencesdialog.h b/utils/themeeditor/gui/preferencesdialog.h new file mode 100644 index 0000000..e28a830 --- /dev/null +++ b/utils/themeeditor/gui/preferencesdialog.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef PREFERENCESDIALOG_H +#define PREFERENCESDIALOG_H + +#include +#include + +namespace Ui { + class PreferencesDialog; +} + +class PreferencesDialog : public QDialog { + Q_OBJECT +public: + PreferencesDialog(QWidget *parent = 0); + ~PreferencesDialog(); + + static void setButtonColor(QPushButton* button, QColor color) + { + QString style = "* { background:" + color.name() + "}"; + button->setStyleSheet(style); + } + +public slots: + void accept(); + void reject(); + +private slots: + void colorClicked(); + +private: + Ui::PreferencesDialog *ui; + + void loadSettings(); + void loadColors(); + void loadFont(); + void saveSettings(); + void saveColors(); + void saveFont(); + + void setupUI(); + + QColor fgColor; + QColor bgColor; + QColor errorColor; + QColor commentColor; + QColor escapedColor; + QColor tagColor; + QColor conditionalColor; +}; + +#endif // PREFERENCESDIALOG_H diff --git a/utils/themeeditor/gui/preferencesdialog.ui b/utils/themeeditor/gui/preferencesdialog.ui new file mode 100644 index 0000000..1da7811 --- /dev/null +++ b/utils/themeeditor/gui/preferencesdialog.ui @@ -0,0 +1,306 @@ + + + PreferencesDialog + + + + 0 + 0 + 370 + 370 + + + + Preferences + + + + + + QTabWidget::North + + + 0 + + + + Editor + + + + + + + + Font + + + + + + + + + + + + + + Size + + + + + + + 12 + + + + + + + + + + + Foreground Colour + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + fgButton + + + + + + + false + + + Click To Change + + + + + + + + + + + Background Colour + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + bgButton + + + + + + + false + + + Click To Change + + + + + + + + + + + Error Colour + + + errorButton + + + + + + + Click To Change + + + + + + + + + + Highlighting + + + + + + + + Comment + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + commentButton + + + + + + + false + + + Click To Change + + + false + + + + + + + + + + + Escaped Character + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + escapedButton + + + + + + + false + + + Click To Change + + + + + + + + + + + Conditional + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + conditionalButton + + + + + + + false + + + Click To Change + + + + + + + + + + + Tag + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + tagButton + + + + + + + false + + + Click To Change + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + PreferencesDialog + accept() + + + 257 + 360 + + + 157 + 274 + + + + + buttonBox + rejected() + PreferencesDialog + reject() + + + 325 + 360 + + + 286 + 274 + + + + + diff --git a/utils/themeeditor/gui/skindocument.cpp b/utils/themeeditor/gui/skindocument.cpp new file mode 100644 index 0000000..82c7106 --- /dev/null +++ b/utils/themeeditor/gui/skindocument.cpp @@ -0,0 +1,311 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your optiyouon) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "skindocument.h" + +#include +#include +#include +#include +#include + +#include + +SkinDocument::SkinDocument(QLabel* statusLabel, QWidget *parent) : + TabContent(parent), statusLabel(statusLabel) +{ + setupUI(); + + titleText = "Untitled"; + fileName = ""; + saved = ""; + parseStatus = tr("Empty document"); + blockUpdate = false; +} + +SkinDocument::SkinDocument(QLabel* statusLabel, QString file, QWidget *parent): + TabContent(parent), fileName(file), statusLabel(statusLabel) +{ + setupUI(); + blockUpdate = false; + + /* Loading the file */ + if(QFile::exists(fileName)) + { + QFile fin(fileName); + fin.open(QFile::ReadOnly); + editor->document()->setPlainText(QString(fin.readAll())); + saved = editor->document()->toPlainText(); + editor->setTextCursor(QTextCursor(editor->document()->begin())); + fin.close(); + } + + /* Setting the title */ + QStringList decomposed = fileName.split('/'); + titleText = decomposed.last(); +} + +SkinDocument::~SkinDocument() +{ + delete highlighter; + delete model; +} + +void SkinDocument::connectPrefs(PreferencesDialog* prefs) +{ + QObject::connect(prefs, SIGNAL(accepted()), + this, SLOT(settingsChanged())); + QObject::connect(prefs, SIGNAL(accepted()), + highlighter, SLOT(loadSettings())); +} + +bool SkinDocument::requestClose() +{ + /* Storing the response in blockUpdate will also block updates to the + status bar if the tab is being closed */ + if(editor->document()->toPlainText() != saved) + { + /* Spawning the "Are you sure?" dialog */ + QMessageBox confirm(this); + confirm.setWindowTitle(tr("Confirm Close")); + confirm.setText(titleText + tr(" has been modified.")); + confirm.setInformativeText(tr("Do you want to save your changes?")); + confirm.setStandardButtons(QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + confirm.setDefaultButton(QMessageBox::Save); + int confirmation = confirm.exec(); + + switch(confirmation) + { + case QMessageBox::Save: + save(); + /* After calling save, make sure the user actually went through */ + if(editor->document()->toPlainText() != saved) + blockUpdate = false; + else + blockUpdate = true; + break; + + case QMessageBox::Discard: + blockUpdate = true; + break; + + case QMessageBox::Cancel: + blockUpdate = false; + break; + } + } + else + blockUpdate = true; + + return blockUpdate; +} + +void SkinDocument::setupUI() +{ + /* Setting up the text edit */ + layout = new QHBoxLayout; + editor = new CodeEditor(this); + editor->setLineWrapMode(QPlainTextEdit::NoWrap); + layout->addWidget(editor); + + setLayout(layout); + + /* Attaching the syntax highlighter */ + highlighter = new SkinHighlighter(editor->document()); + + /* Setting up the model */ + model = new ParseTreeModel(""); + + /* Connecting the editor's signal */ + QObject::connect(editor, SIGNAL(textChanged()), + this, SLOT(codeChanged())); + QObject::connect(editor, SIGNAL(cursorPositionChanged()), + this, SLOT(cursorChanged())); + + settingsChanged(); +} + +void SkinDocument::settingsChanged() +{ + /* Setting the editor colors */ + QSettings settings; + settings.beginGroup("SkinDocument"); + + QColor fg = settings.value("fgColor", Qt::black).value(); + QColor bg = settings.value("bgColor", Qt::white).value(); + QPalette palette; + palette.setColor(QPalette::All, QPalette::Base, bg); + palette.setColor(QPalette::All, QPalette::Text, fg); + editor->setPalette(palette); + + QColor highlight = settings.value("errorColor", Qt::red).value(); + editor->setErrorColor(highlight); + + /* Setting the font */ + QFont def("Monospace"); + def.setStyleHint(QFont::TypeWriter); + QFont family = settings.value("fontFamily", def).value(); + family.setPointSize(settings.value("fontSize", 12).toInt()); + editor->setFont(family); + + editor->repaint(); + + settings.endGroup(); + +} + +void SkinDocument::cursorChanged() +{ + if(editor->isError(editor->textCursor().blockNumber() + 1)) + { + QTextCursor line = editor->textCursor(); + line.movePosition(QTextCursor::StartOfLine); + line.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor); + skin_parse(line.selectedText().toAscii()); + if(skin_error_line() > 0) + parseStatus = tr("Error on line ") + + QString::number(line.blockNumber() + 1) + tr(": ") + + skin_error_message(); + statusLabel->setText(parseStatus); + } + else if(editor->hasErrors()) + { + parseStatus = tr("Errors in document"); + statusLabel->setText(parseStatus); + } + else + { + emit lineChanged(editor->textCursor().blockNumber() + 1); + } + +} + +void SkinDocument::codeChanged() +{ + if(blockUpdate) + return; + + if(editor->document()->isEmpty()) + { + parseStatus = tr("Empty document"); + statusLabel->setText(parseStatus); + return; + } + + editor->clearErrors(); + parseStatus = model->changeTree(editor->document()-> + toPlainText().toAscii()); + if(skin_error_line() > 0) + parseStatus = tr("Errors in document"); + statusLabel->setText(parseStatus); + + /* Highlighting if an error was found */ + if(skin_error_line() > 0) + { + editor->addError(skin_error_line()); + + /* Now we're going to attempt parsing again at each line, until we find + one that won't error out*/ + QTextDocument doc(editor->document()->toPlainText()); + int base = 0; + while(skin_error_line() > 0 && !doc.isEmpty()) + { + QTextCursor rest(&doc); + + for(int i = 0; i < skin_error_line(); i++) + rest.movePosition(QTextCursor::NextBlock, + QTextCursor::KeepAnchor); + if(skin_error_line() == doc.blockCount()) + rest.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); + + rest.removeSelectedText(); + base += skin_error_line(); + + skin_parse(doc.toPlainText().toAscii()); + + if(skin_error_line() > 0) + editor->addError(base + skin_error_line()); + + } + } + + if(editor->document()->toPlainText() != saved) + emit titleChanged(titleText + QChar('*')); + else + emit titleChanged(titleText); + + cursorChanged(); + +} + +void SkinDocument::save() +{ + QFile fout(fileName); + + if(!fout.exists()) + { + saveAs(); + return; + } + + fout.open(QFile::WriteOnly); + fout.write(editor->document()->toPlainText().toAscii()); + fout.close(); + + saved = editor->document()->toPlainText(); + QStringList decompose = fileName.split('/'); + titleText = decompose.last(); + emit titleChanged(titleText); + +} + +void SkinDocument::saveAs() +{ + /* Determining the directory to open */ + QString directory = fileName; + + QSettings settings; + settings.beginGroup("SkinDocument"); + if(directory == "") + directory = settings.value("defaultDirectory", "").toString(); + + fileName = QFileDialog::getSaveFileName(this, tr("Save Document"), + directory, fileFilter()); + directory = fileName; + if(fileName == "") + return; + + directory.chop(fileName.length() - fileName.lastIndexOf('/') - 1); + settings.setValue("defaultDirectory", directory); + settings.endGroup(); + + QFile fout(fileName); + fout.open(QFile::WriteOnly); + fout.write(editor->document()->toPlainText().toAscii()); + fout.close(); + + saved = editor->document()->toPlainText(); + QStringList decompose = fileName.split('/'); + titleText = decompose[decompose.count() - 1]; + emit titleChanged(titleText); + +} diff --git a/utils/themeeditor/gui/skindocument.h b/utils/themeeditor/gui/skindocument.h new file mode 100644 index 0000000..c6449ca --- /dev/null +++ b/utils/themeeditor/gui/skindocument.h @@ -0,0 +1,96 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef SKINDOCUMENT_H +#define SKINDOCUMENT_H + +#include +#include +#include + +#include "skinhighlighter.h" +#include "parsetreemodel.h" +#include "preferencesdialog.h" +#include "codeeditor.h" +#include "tabcontent.h" + +class SkinDocument : public TabContent +{ +Q_OBJECT +public: + static QString fileFilter() + { + return tr("WPS Files (*.wps *.rwps);;" + "SBS Files (*.sbs *.rsbs);;" + "FMS Files (*.fms *.rfms);;" + "All Skin Files (*.wps *.rwps *.sbs " + "*.rsbs *.fms *.rfms);;" + "All Files (*.*)"); + } + + SkinDocument(QLabel* statusLabel, QWidget *parent = 0); + SkinDocument(QLabel* statusLabel, QString file, QWidget* parent = 0); + virtual ~SkinDocument(); + + void connectPrefs(PreferencesDialog* prefs); + + ParseTreeModel* getModel(){ return model; } + QString file() const{ return fileName; } + QString title() const{ return titleText; } + QString getStatus(){ return parseStatus; } + void genCode(){ editor->document()->setPlainText(model->genCode()); } + + void save(); + void saveAs(); + + bool requestClose(); + + TabType type() const{ return Skin; } + +signals: + +public slots: + void settingsChanged(); + void cursorChanged(); + +private slots: + void codeChanged(); + +private: + void setupUI(); + + QString titleText; + QString fileName; + QString saved; + QString parseStatus; + + QLayout* layout; + CodeEditor* editor; + + SkinHighlighter* highlighter; + ParseTreeModel* model; + + QLabel* statusLabel; + + bool blockUpdate; +}; + +#endif // SKINDOCUMENT_H diff --git a/utils/themeeditor/gui/skinhighlighter.cpp b/utils/themeeditor/gui/skinhighlighter.cpp new file mode 100644 index 0000000..25a479f --- /dev/null +++ b/utils/themeeditor/gui/skinhighlighter.cpp @@ -0,0 +1,172 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "skinhighlighter.h" + +#include + +SkinHighlighter::SkinHighlighter(QTextDocument* doc) + :QSyntaxHighlighter(doc) +{ + loadSettings(); +} + +SkinHighlighter::~SkinHighlighter() +{ + +} + +void SkinHighlighter::highlightBlock(const QString& text) +{ + for(int i = 0; i < text.length(); i++) + { + QChar c = text[i]; + + /* Checking for delimiters */ + if(c == ARGLISTOPENSYM + || c == ARGLISTCLOSESYM + || c == ARGLISTSEPERATESYM) + setFormat(i, 1, tag); + + if(c == ENUMLISTOPENSYM + || c == ENUMLISTCLOSESYM + || c == ENUMLISTSEPERATESYM) + setFormat(i, 1, conditional); + + /* Checking for comments */ + if(c == COMMENTSYM) + { + setFormat(i, text.length() - i, comment); + return; + } + + if(c == TAGSYM) + { + if(text.length() - i < 2) + return; + + if(find_escape_character(text[i + 1].toAscii())) + { + /* Checking for escaped characters */ + + setFormat(i, 2, escaped); + i++; + } + else if(text[i + 1] != CONDITIONSYM) + { + /* Checking for normal tags */ + + char lookup[3]; + struct tag_info* found = 0; + + /* First checking for a two-character tag name */ + lookup[2] = '\0'; + + if(text.length() - i >= 3) + { + lookup[0] = text[i + 1].toAscii(); + lookup[1] = text[i + 2].toAscii(); + + found = find_tag(lookup); + } + + if(found) + { + setFormat(i, 3, tag); + i += 2; + } + else + { + lookup[1] = '\0'; + lookup[0] = text[i + 1].toAscii(); + found = find_tag(lookup); + + if(found) + { + setFormat(i, 2, tag); + i++; + } + } + + } + else if(text[i + 1] == CONDITIONSYM) + { + /* Checking for conditional tags */ + + if(text.length() - i < 3) + return; + + char lookup[3]; + struct tag_info* found = 0; + + lookup[2] = '\0'; + + if(text.length() - i >= 4) + { + lookup[0] = text[i + 2].toAscii(); + lookup[1] = text[i + 3].toAscii(); + + found = find_tag(lookup); + } + + if(found) + { + setFormat(i, 4, conditional); + i += 3; + } + else + { + lookup[1] = '\0'; + lookup[0] = text[i + 2].toAscii(); + + found = find_tag(lookup); + + if(found) + { + setFormat(i, 3, conditional); + i += 2; + } + } + + } + } + } +} + +void SkinHighlighter::loadSettings() +{ + QSettings settings; + + settings.beginGroup("SkinHighlighter"); + + /* Loading the highlighting colors */ + tag = settings.value("tagColor", QColor(180,0,0)).value(); + conditional = settings.value("conditionalColor", + QColor(0, 0, 180)).value(); + escaped = settings.value("escapedColor", + QColor(120,120,120)).value(); + comment = settings.value("commentColor", + QColor(0, 180, 0)).value(); + + settings.endGroup(); + + rehighlight(); +} diff --git a/utils/themeeditor/gui/skinhighlighter.h b/utils/themeeditor/gui/skinhighlighter.h new file mode 100644 index 0000000..4d5c68b --- /dev/null +++ b/utils/themeeditor/gui/skinhighlighter.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef SKINHIGHLIGHTER_H +#define SKINHIGHLIGHTER_H + +#include +#include + +#include "tag_table.h" +#include "symbols.h" + +class SkinHighlighter : public QSyntaxHighlighter +{ +Q_OBJECT +public: + /* + * font - The font used for all text + * normal - The normal text color + * escaped - The color for escaped characters + * tag - The color for tags and their delimiters + * conditional - The color for conditionals and their delimiters + * + */ + SkinHighlighter(QTextDocument* doc); + virtual ~SkinHighlighter(); + + void highlightBlock(const QString& text); + +public slots: + void loadSettings(); + +private: + QColor escaped; + QColor tag; + QColor conditional; + QColor comment; + +}; + +#endif // SKINHIGHLIGHTER_H diff --git a/utils/themeeditor/gui/skinviewer.cpp b/utils/themeeditor/gui/skinviewer.cpp new file mode 100644 index 0000000..152450e --- /dev/null +++ b/utils/themeeditor/gui/skinviewer.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "skinviewer.h" +#include "ui_skinviewer.h" + +SkinViewer::SkinViewer(QWidget *parent) : + QWidget(parent), + ui(new Ui::SkinViewer) +{ + ui->setupUi(this); + + QObject::connect(ui->zoomOutButton, SIGNAL(pressed()), + this, SLOT(zoomOut())); + QObject::connect(ui->zoomInButton, SIGNAL(pressed()), + this, SLOT(zoomIn())); +} + +SkinViewer::~SkinViewer() +{ + delete ui; +} + +void SkinViewer::changeEvent(QEvent *e) +{ + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + +void SkinViewer::setScene(QGraphicsScene *scene) +{ + ui->viewer->setScene(scene); +} + +void SkinViewer::zoomIn() +{ + ui->viewer->scale(1.2, 1.2); +} + +void SkinViewer::zoomOut() +{ + ui->viewer->scale(1/1.2, 1/1.2); +} diff --git a/utils/themeeditor/gui/skinviewer.h b/utils/themeeditor/gui/skinviewer.h new file mode 100644 index 0000000..599a204 --- /dev/null +++ b/utils/themeeditor/gui/skinviewer.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef SKINVIEWER_H +#define SKINVIEWER_H + +#include +#include + +namespace Ui { + class SkinViewer; +} + +class SkinViewer : public QWidget { + Q_OBJECT +public: + SkinViewer(QWidget *parent = 0); + ~SkinViewer(); + + void setScene(QGraphicsScene* scene); + +public slots: + void zoomIn(); + void zoomOut(); + +protected: + void changeEvent(QEvent *e); + +private: + Ui::SkinViewer *ui; +}; + +#endif // SKINVIEWER_H diff --git a/utils/themeeditor/gui/skinviewer.ui b/utils/themeeditor/gui/skinviewer.ui new file mode 100644 index 0000000..ed260d0 --- /dev/null +++ b/utils/themeeditor/gui/skinviewer.ui @@ -0,0 +1,42 @@ + + + SkinViewer + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + + + + + + Zoom In + + + + + + + Zoom Out + + + + + + + + + + diff --git a/utils/themeeditor/gui/tabcontent.h b/utils/themeeditor/gui/tabcontent.h new file mode 100644 index 0000000..1b153f7 --- /dev/null +++ b/utils/themeeditor/gui/tabcontent.h @@ -0,0 +1,35 @@ +#ifndef TABCONTENT_H +#define TABCONTENT_H + +#include + +class TabContent : public QWidget +{ +Q_OBJECT +public: + enum TabType + { + Skin, + Config + }; + + TabContent(QWidget *parent = 0): QWidget(parent){ } + + virtual TabType type() const = 0; + virtual QString title() const = 0; + virtual QString file() const = 0; + + virtual void save() = 0; + virtual void saveAs() = 0; + + virtual bool requestClose() = 0; + +signals: + void titleChanged(QString); + void lineChanged(int); + +public slots: + +}; + +#endif // TABCONTENT_H -- cgit v1.1