Sat, 07 Sep 2013 13:23:09 +0300
Merge branch 'master' into gl, reworked stuff
Conflicts:
src/gldraw.cpp
src/gldraw.h
src/aboutDialog.cpp | file | annotate | diff | comparison | revisions | |
src/aboutDialog.h | file | annotate | diff | comparison | revisions | |
src/gldata.cpp | file | annotate | diff | comparison | revisions | |
src/gldata.h | file | annotate | diff | comparison | revisions | |
src/gldraw.cpp | file | annotate | diff | comparison | revisions | |
src/gldraw.h | file | annotate | diff | comparison | revisions | |
src/labeledwidget.h | file | annotate | diff | comparison | revisions | |
src/types.h | file | annotate | diff | comparison | revisions |
--- a/.gitignore Fri Aug 16 11:05:21 2013 +0300 +++ b/.gitignore Sat Sep 07 13:23:09 2013 +0300 @@ -4,4 +4,5 @@ Makefile ldforge *.dat -debug_lastOutput \ No newline at end of file +debug_lastOutput +.kdev_include_paths \ No newline at end of file
--- a/changelog.txt Fri Aug 16 11:05:21 2013 +0300 +++ b/changelog.txt Sat Sep 07 13:23:09 2013 +0300 @@ -6,17 +6,34 @@ - Added close, close all and save all actions. - Added ability to download parts from the Parts Tracker or from a custom-specified URL. If the resulting file contains references to unknown files, LDForge attempts to recursively download all of them. -- Color icon border now reflects the color's edge color. -- Changing to draw mode while in free camera now causes the camera to be changed to top. +- Converted the configuration code to use QSettings, in practice this means the configuration file moved to + the registry under Windows and into ~/.config/LDForge under Linux. Unfortunately this means settings get + lost during transition from version 0.2 and 0.3. - Corrections to the primitive generator: - Fixed: "Hi-Res" was not prepended to the names of 48/ primitives. - Fixed: Checking the Hi-Res option would not allow segment values over 16. - Added support for multiple spaces before the ring number. +- Changing to draw mode while in free camera now causes the camera to be changed to top. +- Added config fields for default name/username/license. This data will be automatically filled + into forms that require such information. +- Upon first start the configuration prompt pops up on its own, defaulting on the profile tab. This + way the user can fill in the profile data on the first start and get that out of the way (and + gives the opportunity to see the other config fields) +- Added new action "Add History Line" for quickly inserting 0 !HISTORY lines to headers +- Added new action "Go to line", default shortcut Ctrl-G. It should be obvious what it does. +- Added support for logoed studs, this should satisfy Steffen. :p - Added support for '0 BFC CLIP' and '0 BFC NOCLIP' and added auto-correction from errorneous MLCAD syntax ('0 BFC CERTIFY CLIP'). +- When an external program is attempted to be used without a binary path defined, one will be asked + with an input dialog instead of being told to go to configuration to set the path. +- When adding edges with Intersector (which is done with Isecalc), the user is prompted for Isecalc's + path now as well if necessary instead of just ignoring it and not adding the edgelines. +- BFC red/green view and black edges no longer default to true. - If the vertex snapper finds a vertex closer than 4 pixels, it likely is the vertex being looked for and the algorithm can terminate early, hopefully this will save a few cycles on large parts. - The camera icons now draw real tooltips instead of emulated ones. +- Color icon border now reflects the color's edge color. +- Fixed: The message log was still written with black text with dark backgrounds. ================================================= == Changes in version 0.2-alpha
--- a/mkqrc.sh Fri Aug 16 11:05:21 2013 +0300 +++ b/mkqrc.sh Sat Sep 07 13:23:09 2013 +0300 @@ -4,7 +4,6 @@ FILES=$(echo ./icons/*.* data/*.* LICENSE LICENSE.icons) printf "" > $QRCFILE - printf "<!DOCTYPE RCC>\n<RCC version=\"1.0\">\n<qresource>\n" >> $QRCFILE for f in $FILES; do
--- a/src/aboutDialog.cpp Fri Aug 16 11:05:21 2013 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * LDForge: LDraw parts authoring CAD - * Copyright (C) 2013 Santeri Piippo - * - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <QDesktopServices> -#include <QPushButton> -#include <QUrl> -#include "aboutDialog.h" -#include "ui_about.h" -#include "gui.h" - -AboutDialog::AboutDialog (QWidget* parent, Qt::WindowFlags f) : - QDialog (parent, f) { - - Ui::AboutUI ui; - ui.setupUi (this); - ui.versionInfo->setText (fmt (tr ("LDForge %1"), fullVersionString())); - - QPushButton* mailButton = new QPushButton; - mailButton->setText ("Contact"); - mailButton->setIcon (getIcon ("mail")); - ui.buttonBox->addButton (static_cast<QAbstractButton*> (mailButton), QDialogButtonBox::HelpRole); - connect (ui.buttonBox, SIGNAL (helpRequested()), this, SLOT (slot_mail())); - - setWindowTitle ("About " APPNAME); -} - -void AboutDialog::slot_mail() { - QDesktopServices::openUrl (QUrl ("mailto:Santeri Piippo <arezey@gmail.com>?subject=LDForge")); -} - -#include "build/moc_aboutDialog.cpp" \ No newline at end of file
--- a/src/aboutDialog.h Fri Aug 16 11:05:21 2013 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * LDForge: LDraw parts authoring CAD - * Copyright (C) 2013 Santeri Piippo - * - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef ZZ_ABOUTDIALOG_H -#define ZZ_ABOUTDIALOG_H - -#include <QDialog> -#include "common.h" -#include "types.h" - -class QPushButton; - -class AboutDialog : public QDialog { - Q_OBJECT - -public: - AboutDialog (QWidget* parent = null, Qt::WindowFlags f = 0); - -private slots: - void slot_mail(); -}; - -#endif // ZZ_ABOUTDIALOG_H \ No newline at end of file
--- a/src/actions.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/actions.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,3 +1,21 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 Santeri Piippo + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + act (New) act (NewFile) act (Open) @@ -85,5 +103,7 @@ act (RotateZNeg) act (RotateZPos) act (RotationPoint) +act (AddHistoryLine) +act (JumpTo) #undef act \ No newline at end of file
--- a/src/addObjectDialog.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/addObjectDialog.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,30 +1,30 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <qgridlayout.h> -#include <qcheckbox.h> -#include <qdialogbuttonbox.h> -#include <qspinbox.h> -#include <qlabel.h> -#include <qlistwidget.h> -#include <qtreewidget.h> -#include <qlineedit.h> -#include <qpushbutton.h> +#include <QGridLayout> +#include <QCheckBox> +#include <QDialogButtonBox> +#include <QSpinBox> +#include <QLabel> +#include <QListWidget> +#include <QTreeWidget> +#include <QLineEdit> +#include <QPushButton> #include "gui.h" #include "addObjectDialog.h" #include "file.h" @@ -35,6 +35,8 @@ #include "misc.h" #include "primitives.h" +// ============================================================================= +// ----------------------------------------------------------------------------- class SubfileListItem : public QTreeWidgetItem { PROPERTY (Primitive*, primInfo, setPrimInfo) @@ -46,8 +48,7 @@ }; // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- AddObjectDialog::AddObjectDialog (const LDObject::Type type, LDObject* obj, QWidget* parent) : QDialog (parent) { setlocale (LC_ALL, "C"); @@ -58,7 +59,7 @@ case LDObject::Comment: le_comment = new QLineEdit; if (obj) - le_comment->setText (static_cast<LDCommentObject*> (obj)->text); + le_comment->setText (static_cast<LDComment*> (obj)->text); le_comment->setMinimumWidth (384); break; @@ -72,7 +73,7 @@ break; case LDObject::Quad: - case LDObject::CondLine: + case LDObject::CndLine: coordCount = 12; break; @@ -81,62 +82,60 @@ break; case LDObject::BFC: - rb_bfcType = new RadioBox ("Statement", {}, 0, Qt::Vertical); + rb_bfcType = new RadioGroup ("Statement", {}, 0, Qt::Vertical); - for (int i = 0; i < LDBFCObject::NumStatements; ++i) { + for (int i = 0; i < LDBFC::NumStatements; ++i) { // Separate these in two columns - if (i == LDBFCObject::NumStatements / 2) + if (i == LDBFC::NumStatements / 2) rb_bfcType->rowBreak(); - rb_bfcType->addButton (LDBFCObject::statements[i]); + rb_bfcType->addButton (LDBFC::statements[i]); } if (obj) - rb_bfcType->setValue ((int) static_cast<LDBFCObject*> (obj)->type); + rb_bfcType->setValue ((int) static_cast<LDBFC*> (obj)->type); break; case LDObject::Subfile: - { - coordCount = 3; - - // If the primitive lister is busy writing data, we have to wait - // for that to happen first. This should be quite considerably rare. - while (primitiveLoaderBusy()) - ; - - tw_subfileList = new QTreeWidget(); - tw_subfileList->setHeaderLabel (tr ("Primitives")); + coordCount = 3; + + // If the primitive lister is busy writing data, we have to wait + // for that to happen first. This should be quite considerably rare. + while (primitiveLoaderBusy()) + ; + + tw_subfileList = new QTreeWidget(); + tw_subfileList->setHeaderLabel (tr ("Primitives")); + + for (PrimitiveCategory& cat : g_PrimitiveCategories) { + SubfileListItem* parentItem = new SubfileListItem (tw_subfileList, null); + parentItem->setText (0, cat.name()); + QList<QTreeWidgetItem*> subfileItems; - for (PrimitiveCategory& cat : g_PrimitiveCategories) { - SubfileListItem* parentItem = new SubfileListItem (tw_subfileList, null); - parentItem->setText (0, cat.name()); - QList<QTreeWidgetItem*> subfileItems; + for (Primitive& prim : cat.prims) { + SubfileListItem* item = new SubfileListItem (parentItem, &prim); + item->setText (0, fmt ("%1 - %2", prim.name, prim.title)); + subfileItems << item; - for (Primitive& prim : cat.prims) { - SubfileListItem* item = new SubfileListItem (parentItem, &prim); - item->setText (0, fmt ("%1 - %2", prim.name, prim.title)); - subfileItems << item; - - // If this primitive is the one the current object points to, - // select it by default - if (obj && static_cast<LDSubfileObject*> (obj)->fileInfo()->name() == prim.name) - tw_subfileList->setCurrentItem (item); - } - - tw_subfileList->addTopLevelItem (parentItem); + // If this primitive is the one the current object points to, + // select it by default + if (obj && static_cast<LDSubfile*> (obj)->fileInfo()->name() == prim.name) + tw_subfileList->setCurrentItem (item); } - connect (tw_subfileList, SIGNAL (itemSelectionChanged()), this, SLOT (slot_subfileTypeChanged())); - lb_subfileName = new QLabel ("File:"); - le_subfileName = new QLineEdit; - le_subfileName->setFocus(); - - if (obj) { - LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); - le_subfileName->setText (ref->fileInfo()->name()); - } - break; + tw_subfileList->addTopLevelItem (parentItem); } + + connect (tw_subfileList, SIGNAL (itemSelectionChanged()), this, SLOT (slot_subfileTypeChanged())); + lb_subfileName = new QLabel ("File:"); + le_subfileName = new QLineEdit; + le_subfileName->setFocus(); + + if (obj) { + LDSubfile* ref = static_cast<LDSubfile*> (obj); + le_subfileName->setText (ref->fileInfo()->name()); + } + break; default: critical (fmt ("Unhandled LDObject type %1 (%2) in AddObjectDialog", (int) type, typeName)); @@ -154,7 +153,7 @@ if (obj != null) colnum = obj->color(); else - colnum = (type == LDObject::CondLine || type == LDObject::Line) ? edgecolor : maincolor; + colnum = (type == LDObject::CndLine || type == LDObject::Line) ? edgecolor : maincolor; pb_color = new QPushButton; setButtonBackground (pb_color, colnum); @@ -173,7 +172,7 @@ switch (type) { case LDObject::Line: - case LDObject::CondLine: + case LDObject::CndLine: case LDObject::Triangle: case LDObject::Quad: // Apply coordinates @@ -246,8 +245,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void AddObjectDialog::setButtonBackground (QPushButton* button, short colnum) { LDColor* col = getColor (colnum); @@ -259,8 +257,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- str AddObjectDialog::currentSubfileName() { SubfileListItem* item = static_cast<SubfileListItem*> (tw_subfileList->currentItem()); @@ -271,16 +268,14 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void AddObjectDialog::slot_colorButtonClicked() { ColorSelector::getColor (colnum, colnum, this); setButtonBackground (pb_color, colnum); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void AddObjectDialog::slot_subfileTypeChanged() { str name = currentSubfileName(); @@ -289,7 +284,8 @@ } // ============================================================================= -template<class T> T* initObj (LDObject*& obj) { +// ----------------------------------------------------------------------------- +template<class T> static T* initObj (LDObject*& obj) { if (obj == null) obj = new T; @@ -297,8 +293,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void AddObjectDialog::staticDialog (const LDObject::Type type, LDObject* obj) { setlocale (LC_ALL, "C"); @@ -320,7 +315,7 @@ return; if (type == LDObject::Subfile) { - List<str> matrixstrvals = container_cast<QStringList, List<str>> (str (dlg.le_matrix->text()).split (" ")); + QStringList matrixstrvals = dlg.le_matrix->text().split (" "); if (matrixstrvals.size() == 9) { double matrixvals[9]; @@ -336,7 +331,7 @@ switch (type) { case LDObject::Comment: { - LDCommentObject* comm = initObj<LDCommentObject> (obj); + LDComment* comm = initObj<LDComment> (obj); comm->text = dlg.le_comment->text(); } break; @@ -344,7 +339,7 @@ case LDObject::Line: case LDObject::Triangle: case LDObject::Quad: - case LDObject::CondLine: + case LDObject::CndLine: if (!obj) obj = LDObject::getDefault (type); @@ -359,14 +354,14 @@ case LDObject::BFC: { - LDBFCObject* bfc = initObj<LDBFCObject> (obj); - bfc->type = (LDBFCObject::Type) dlg.rb_bfcType->value(); + LDBFC* bfc = initObj<LDBFC> (obj); + bfc->type = (LDBFC::Type) dlg.rb_bfcType->value(); } break; case LDObject::Vertex: { - LDVertexObject* vert = initObj<LDVertexObject> (obj); + LDVertex* vert = initObj<LDVertex> (obj); for (const Axis ax : g_Axes) vert->pos[ax] = dlg.dsb_coords[ax]->value(); @@ -385,7 +380,7 @@ return; } - LDSubfileObject* ref = initObj<LDSubfileObject> (obj); + LDSubfile* ref = initObj<LDSubfile> (obj); for (const Axis ax : g_Axes) ref->setCoordinate (ax, dlg.dsb_coords[ax]->value()); @@ -408,6 +403,4 @@ } g_win->fullRefresh(); -} - -#include "build/moc_addObjectDialog.cpp" \ No newline at end of file +} \ No newline at end of file
--- a/src/addObjectDialog.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/addObjectDialog.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -24,7 +24,7 @@ class QTreeWidgetItem; class QLineEdit; -class RadioBox; +class RadioGroup; class QCheckBox; class QSpinBox; class QLabel; @@ -50,7 +50,7 @@ QPushButton* pb_color; // BFC-related widgets - RadioBox* rb_bfcType; + RadioGroup* rb_bfcType; // Subfile stuff QTreeWidget* tw_subfileList;
--- a/src/colorSelectDialog.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/colorSelectDialog.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -14,6 +14,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. + * ===================================================================== + * + * colorSelectDialog.cpp: Color selector box. */ #include <QGraphicsScene> @@ -32,47 +35,43 @@ static const int g_numColumns = 16; static const short g_squareSize = 32; -extern_cfg (str, gl_maincolor); -extern_cfg (float, gl_maincolor_alpha); +extern_cfg (String, gl_maincolor); +extern_cfg (Float, gl_maincolor_alpha); // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- ColorSelector::ColorSelector (short defval, QWidget* parent) : QDialog (parent) { // Remove the default color if it's invalid if (!::getColor (defval)) defval = -1; - + m_firstResize = true; ui = new Ui_ColorSelUI; ui->setupUi (this); - + m_scene = new QGraphicsScene; ui->viewport->setScene (m_scene); setSelection (::getColor (defval)); - + // not really an icon but eh m_scene->setBackgroundBrush (getIcon ("checkerboard")); - drawScene(); - + int width = viewportWidth(); ui->viewport->setMinimumWidth (width); ui->viewport->setMaximumWidth (width); - + drawColorInfo(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- ColorSelector::~ColorSelector() { delete ui; } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ColorSelector::drawScene() { const int numCols = g_numColumns; const int square = g_squareSize; @@ -119,22 +118,19 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- int ColorSelector::numRows() const { return (MAX_COLORS / g_numColumns); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- int ColorSelector::viewportWidth() const { return g_numColumns * g_squareSize + 21; } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ColorSelector::drawColorInfo() { if (!sel()) { ui->colorLabel->setText ("---"); @@ -145,8 +141,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ColorSelector::resizeEvent (QResizeEvent* ev) { // If this is the first resize, check if we need to scroll down to see the // currently selected color. We cannot do this in the constructor because the @@ -167,8 +162,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ColorSelector::mousePressEvent (QMouseEvent* event) { QPointF scenepos = ui->viewport->mapToScene (event->pos()); @@ -187,8 +181,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- bool ColorSelector::getColor (short& val, short int defval, QWidget* parent) { ColorSelector dlg (defval, parent); @@ -198,6 +191,4 @@ } return false; -} - -#include "build/moc_colorSelectDialog.cpp" \ No newline at end of file +} \ No newline at end of file
--- a/src/colors.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/colors.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -14,6 +14,11 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. + * ===================================================================== + * + * colors.cpp: LDraw color management. LDConfig.ldr parsing is not here! + * TODO: Make LDColor more full-fledged, add support for direct colors. + * TODO: g_LDColors should probably be a map. */ #include "common.h" @@ -26,20 +31,23 @@ static LDColor* g_LDColors[MAX_COLORS]; +// ============================================================================= +// ----------------------------------------------------------------------------- void initColors() { LDColor* col; print ("%1: initializing color information.\n", __func__); // Always make sure there's 16 and 24 available. They're special like that. col = new LDColor; + col->faceColor = col->hexcode = "#AAAAAA"; - col->faceColor = col->hexcode; col->edgeColor = Qt::black; g_LDColors[maincolor] = col; col = new LDColor; + col->faceColor = + col->edgeColor = col->hexcode = "#000000"; - col->edgeColor = col->faceColor = Qt::black; g_LDColors[edgecolor] = col; parseLDConfig(); @@ -65,7 +73,8 @@ } // ============================================================================= -uchar luma (QColor& col) { +// ----------------------------------------------------------------------------- +int luma (QColor& col) { return (0.2126f * col.red()) + (0.7152f * col.green()) + (0.0722f * col.blue());
--- a/src/colors.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/colors.h Sat Sep 07 13:23:09 2013 +0300 @@ -19,7 +19,7 @@ #ifndef COLORS_H #define COLORS_H -#include <qcolor.h> +#include <QColor> #include "common.h" #define MAX_COLORS 512 @@ -32,7 +32,7 @@ }; void initColors(); -uchar luma (QColor& col); +int luma (QColor& col); // Safely gets a color with the given number or null if no such color. LDColor* getColor (short colnum);
--- a/src/common.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/common.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -56,17 +56,9 @@ #define RELEASE #endif // BUILD_ID -#ifndef RELEASE -# define devf(...) doDevf (__func__, __VA_ARGS__); -#else -# define devf(...) -#endif // RELEASE - #define alias auto& #define elif else if -void doDevf (const char* func, const char* fmtstr, ...); - // Null pointer static const std::nullptr_t null = nullptr;
--- a/src/config.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/config.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -14,6 +14,12 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. + * ===================================================================== + * + * config.cpp: Configuration management. I don't like how unsafe QSettings + * is so this implements a type-safer and idenitifer-safer wrapping system of + * configuration variables. QSettings is used underlyingly, this is a matter + * of interface. */ #include <errno.h> @@ -26,10 +32,13 @@ #include "gui.h" #include "file.h" -config* g_configPointers[MAX_CONFIG]; +Config* g_configPointers[MAX_CONFIG]; static ushort g_cfgPointerCursor = 0; // ============================================================================= +// Get the QSettings object. A portable build refers to a file in the current +// directory, a non-portable build to ~/.config/LDForge or to registry. +// ----------------------------------------------------------------------------- static QSettings* getSettingsObject() { #ifdef PORTABLE # ifdef _WIN32 @@ -43,17 +52,22 @@ #endif // PORTABLE } +Config::Config (const char* name, const char* defstring) : + name (name), m_defstring (defstring) {} + // ============================================================================= // Load the configuration from file -bool config::load() { +// ----------------------------------------------------------------------------- +bool Config::load() { QSettings* settings = getSettingsObject(); - print ("config::load: Loading configuration file from %1...\n", settings->fileName()); + print ("config::load: Loading configuration file from %1\n", settings->fileName()); - for (config* cfg : g_configPointers) { + for (Config* cfg : g_configPointers) { if (!cfg) break; - cfg->loadFromConfig (settings); + QVariant val = settings->value (cfg->name, cfg->defaultVariant()); + cfg->loadFromVariant (val); } settings->deleteLater(); @@ -61,73 +75,20 @@ } // ============================================================================= -void intconfig::loadFromConfig (const QSettings* cfg) { - QVariant val = cfg->value (name, str::number (defval)); - value = val.toInt(); -} - -void floatconfig::loadFromConfig (const QSettings* cfg) { - QVariant val = cfg->value (name, str::number (defval)); - value = val.toFloat(); -} - -void strconfig::loadFromConfig (const QSettings* cfg) { - QVariant val = cfg->value (name, defval); - value = val.toString(); -} - -void boolconfig::loadFromConfig (const QSettings* cfg) { - QVariant val = cfg->value (name, str::number (defval)); - value = val.toBool(); -} - -void keyseqconfig::loadFromConfig (const QSettings* cfg) { - QVariant val = cfg->value (name, defval.toString()); - value = keyseq (val.toString()); -} - -// ============================================================================= -// TODO: make virtual -str config::toString() const { - switch (getType()) { - case Type_int: - return fmt ("%1", static_cast<const intconfig*> (this)->value); - break; - - case Type_str: - return static_cast<const strconfig*> (this)->value; - break; - - case Type_float: - return fmt ("%1", static_cast<const floatconfig*> (this)->value); - break; - - case Type_bool: - return (static_cast<const boolconfig*> (this)->value) ? "true" : "false"; - break; - - case Type_keyseq: - return static_cast<const keyseqconfig*> (this)->value.toString(); - break; - - default: - break; - } - - return ""; -} - -// ============================================================================= // Save the configuration to disk -bool config::save() { +// ----------------------------------------------------------------------------- +bool Config::save() { QSettings* settings = getSettingsObject(); print ("Saving configuration to %1...\n", settings->fileName()); - for (config* cfg : g_configPointers) { + for (Config* cfg : g_configPointers) { if (!cfg) break; - settings->setValue (cfg->name, cfg->toString()); + if (cfg->isDefault()) + continue; + + settings->setValue (cfg->name, cfg->toVariant()); } settings->sync(); @@ -136,8 +97,10 @@ } // ============================================================================= -void config::reset() { - for (config* cfg : g_configPointers) { +// Reset configuration defaults. +// ----------------------------------------------------------------------------- +void Config::reset() { + for (Config* cfg : g_configPointers) { if (!cfg) break; @@ -146,32 +109,27 @@ } // ============================================================================= -str config::filepath (str file) { - return config::dirpath() + DIRSLASH + file; +// Where is the configuration file located at? Note that the Windows build uses +// the registry so only use this with PORTABLE code. +// ----------------------------------------------------------------------------- +str Config::filepath (str file) { + return Config::dirpath() + DIRSLASH + file; } // ============================================================================= -str config::dirpath() { +// Directory of the configuration file. PORTABLE code here as well. +// ----------------------------------------------------------------------------- +str Config::dirpath() { QSettings* cfg = getSettingsObject(); return dirname (cfg->fileName()); } // ============================================================================= -str config::defaultString() const { - str defstring = m_defstring; - - // String types inevitably get extra quotes in their default string due to - // preprocessing stuff. We can only remove them now... - if (getType() == Type_str) { - defstring.remove (0, 1); - defstring.chop (1); - } - - return defstring; -} - -// ============================================================================= -void addConfig (config* ptr) { +// We cannot just add config objects to a list or vector because that would rely +// on the vector's c-tor being called before the configs' c-tors. With global +// variables we cannot assume that!! Therefore we need to use a C-style array here. +// ----------------------------------------------------------------------------- +void Config::addToArray (Config* ptr) { if (g_cfgPointerCursor == 0) memset (g_configPointers, 0, sizeof g_configPointers);
--- a/src/config.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/config.h Sat Sep 07 13:23:09 2013 +0300 @@ -23,6 +23,7 @@ // ============================================================================= #include <QString> +#include <QVariant> #include <QKeySequence> class QSettings; @@ -32,33 +33,33 @@ #define MAX_INI_LINE 512 #define MAX_CONFIG 512 -#define cfg(T, NAME, DEFAULT) T##config NAME (DEFAULT, #NAME, #DEFAULT) -#define extern_cfg(T, NAME) extern T##config NAME +#define cfg(T, NAME, DEFAULT) T##Config NAME (DEFAULT, #NAME, #DEFAULT) +#define extern_cfg(T, NAME) extern T##Config NAME // ========================================================= -class config { +class Config { public: enum Type { - Type_none, - Type_int, - Type_str, - Type_float, - Type_bool, - Type_keyseq, + Int, + String, + Float, + Bool, + KeySequence, + List, }; - config (const char* defstring) : m_defstring (defstring) {} + Config (const char* name, const char* defstring); const char* name; virtual Type getType() const { - return Type_none; + return (Type) 0; } - str toString() const; - str defaultString() const; virtual void resetValue() {} - virtual void loadFromConfig (const QSettings* cfg) { (void) cfg; } + virtual void loadFromVariant (const QVariant& val) { (void) val; } virtual bool isDefault() const { return false; } + virtual QVariant toVariant() const { return QVariant(); } + virtual QVariant defaultVariant() const { return QVariant(); } // ------------------------------------------ static bool load(); @@ -67,38 +68,53 @@ static str dirpath(); static str filepath (str file); +protected: + static void addToArray (Config* ptr); + private: const char* m_defstring; }; -void addConfig (config* ptr); +// ============================================================================= +#define IMPLEMENT_CONFIG(NAME, T) \ + T value, defval; \ + NAME##Config (T defval, const char* name, const char* defstring) : \ + Config (name, defstring), value (defval), defval (defval) \ + { Config::addToArray (this); } \ + \ + operator const T&() const { return value; } \ + Config::Type getType() const override { return Config::NAME; } \ + virtual void resetValue() override { value = defval; } \ + virtual bool isDefault() const override { return value == defval; } \ + virtual QVariant toVariant() const override { return QVariant::fromValue<T> (value); } \ + virtual QVariant defaultVariant() const override { return QVariant::fromValue<T> (defval); } \ + virtual void loadFromVariant (const QVariant& val) override { value = val.value<T>(); } \ -// ============================================================================= #define DEFINE_UNARY_OPERATOR(T, OP) \ T operator OP() { \ return OP value; \ - } \ - + } + #define DEFINE_BINARY_OPERATOR(T, OP) \ T operator OP (const T other) { \ return value OP other; \ - } \ - + } + #define DEFINE_ASSIGN_OPERATOR(T, OP) \ T& operator OP (const T other) { \ return value OP other; \ - } \ - + } + #define DEFINE_COMPARE_OPERATOR(T, OP) \ bool operator OP (const T other) { \ return value OP other; \ - } \ - + } + #define DEFINE_CAST_OPERATOR(T) \ operator T() { \ return (T) value; \ - } \ - + } + #define DEFINE_ALL_COMPARE_OPERATORS(T) \ DEFINE_COMPARE_OPERATOR (T, ==) \ DEFINE_COMPARE_OPERATOR (T, !=) \ @@ -106,42 +122,17 @@ DEFINE_COMPARE_OPERATOR (T, <) \ DEFINE_COMPARE_OPERATOR (T, >=) \ DEFINE_COMPARE_OPERATOR (T, <=) \ - + #define DEFINE_INCREMENT_OPERATORS(T) \ T operator++() { return ++value; } \ T operator++(int) { return value++; } \ T operator--() { return --value; } \ T operator--(int) { return value--; } -#define CONFIGTYPE(T) \ - class T##config : public config - -#define IMPLEMENT_CONFIG(T) \ - T value, defval; \ - \ - T##config (T _defval, const char* _name, const char* defstring) : config (defstring) { \ - value = defval = _defval; \ - name = _name; \ - addConfig (this); \ - } \ - operator const T&() const { \ - return value; \ - } \ - config::Type getType() const override { \ - return config::Type_##T; \ - } \ - virtual void resetValue() { \ - value = defval; \ - } \ - virtual bool isDefault() const { \ - return value == defval; \ - } \ - virtual void loadFromConfig (const QSettings* cfg) override; - // ============================================================================= -CONFIGTYPE (int) { +class IntConfig : public Config { public: - IMPLEMENT_CONFIG (int) + IMPLEMENT_CONFIG (Int, int) DEFINE_ALL_COMPARE_OPERATORS (int) DEFINE_INCREMENT_OPERATORS (int) DEFINE_BINARY_OPERATOR (int, +) @@ -169,24 +160,24 @@ }; // ============================================================================= -CONFIGTYPE (str) { +class StringConfig : public Config { public: - IMPLEMENT_CONFIG (str) - + IMPLEMENT_CONFIG (String, str) + DEFINE_COMPARE_OPERATOR (str, ==) DEFINE_COMPARE_OPERATOR (str, !=) DEFINE_ASSIGN_OPERATOR (str, =) DEFINE_ASSIGN_OPERATOR (str, +=) - qchar operator[] (int n) { + QChar operator[] (int n) { return value[n]; } }; // ============================================================================= -CONFIGTYPE (float) { +class FloatConfig : public Config { public: - IMPLEMENT_CONFIG (float) + IMPLEMENT_CONFIG (Float, float) DEFINE_ALL_COMPARE_OPERATORS (float) DEFINE_INCREMENT_OPERATORS (float) DEFINE_BINARY_OPERATOR (float, +) @@ -200,21 +191,45 @@ }; // ============================================================================= -CONFIGTYPE (bool) { +class BoolConfig : public Config { public: - IMPLEMENT_CONFIG (bool) + IMPLEMENT_CONFIG (Bool, bool) DEFINE_ALL_COMPARE_OPERATORS (bool) DEFINE_ASSIGN_OPERATOR (bool, =) }; // ============================================================================= -typedef QKeySequence keyseq; +class KeySequenceConfig : public Config { +public: + IMPLEMENT_CONFIG (KeySequence, QKeySequence) + DEFINE_ALL_COMPARE_OPERATORS (QKeySequence) + DEFINE_ASSIGN_OPERATOR (QKeySequence, =) +}; -CONFIGTYPE (keyseq) { +// ============================================================================= +class ListConfig : public Config { public: - IMPLEMENT_CONFIG (keyseq) - DEFINE_ALL_COMPARE_OPERATORS (keyseq) - DEFINE_ASSIGN_OPERATOR (keyseq, =) + IMPLEMENT_CONFIG (List, QList<QVariant>) + DEFINE_ASSIGN_OPERATOR (QList<QVariant>, =) + + typedef QList<QVariant>::iterator it; + typedef QList<QVariant>::const_iterator c_it; + + it begin() { + return value.begin(); + } + + c_it begin() const { + return value.constBegin(); + } + + it end() { + return value.end(); + } + + c_it end() const { + return value.constEnd(); + } }; #endif // CONFIG_H \ No newline at end of file
--- a/src/configDialog.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/configDialog.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,19 +1,23 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. + * ===================================================================== + * + * configDialog.cpp: Settings dialog and everything related to it. + * Actual configuration core is in config.cpp. */ #include <QGridLayout> @@ -25,7 +29,6 @@ #include <QDoubleSpinBox> #include <QLineEdit> #include <QCheckBox> - #include "common.h" #include "configDialog.h" #include "file.h" @@ -36,93 +39,73 @@ #include "gldraw.h" #include "ui_config.h" -extern_cfg (str, gl_bgcolor); -extern_cfg (str, gl_maincolor); -extern_cfg (bool, lv_colorize); -extern_cfg (bool, gl_colorbfc); -extern_cfg (float, gl_maincolor_alpha); -extern_cfg (int, gl_linethickness); -extern_cfg (str, gui_colortoolbar); -extern_cfg (bool, edit_schemanticinline); -extern_cfg (bool, gl_blackedges); -extern_cfg (bool, gui_implicitfiles); -extern_cfg (str, net_downloadpath); -extern_cfg (bool, net_guesspaths); -extern_cfg (bool, net_autoclose); +extern_cfg (String, gl_bgcolor); +extern_cfg (String, gl_maincolor); +extern_cfg (Bool, lv_colorize); +extern_cfg (Bool, gl_colorbfc); +extern_cfg (Float, gl_maincolor_alpha); +extern_cfg (Int, gl_linethickness); +extern_cfg (String, gui_colortoolbar); +extern_cfg (Bool, edit_schemanticinline); +extern_cfg (Bool, gl_blackedges); +extern_cfg (Bool, gui_implicitfiles); +extern_cfg (String, net_downloadpath); +extern_cfg (Bool, net_guesspaths); +extern_cfg (Bool, net_autoclose); +extern_cfg (Bool, gl_logostuds); +extern_cfg (String, ld_defaultname); +extern_cfg (String, ld_defaultuser); +extern_cfg (Int, ld_defaultlicense); +extern_cfg (String, prog_ytruder); +extern_cfg (String, prog_rectifier); +extern_cfg (String, prog_intersector); +extern_cfg (String, prog_coverer); +extern_cfg (String, prog_isecalc); +extern_cfg (String, prog_edger2); +extern_cfg (Bool, prog_ytruder_wine); +extern_cfg (Bool, prog_rectifier_wine); +extern_cfg (Bool, prog_intersector_wine); +extern_cfg (Bool, prog_coverer_wine); +extern_cfg (Bool, prog_isecalc_wine); +extern_cfg (Bool, prog_edger2_wine); -extern_cfg (str, prog_ytruder); -extern_cfg (str, prog_rectifier); -extern_cfg (str, prog_intersector); -extern_cfg (str, prog_coverer); -extern_cfg (str, prog_isecalc); -extern_cfg (str, prog_edger2); -extern_cfg (bool, prog_ytruder_wine); -extern_cfg (bool, prog_rectifier_wine); -extern_cfg (bool, prog_intersector_wine); -extern_cfg (bool, prog_coverer_wine); -extern_cfg (bool, prog_isecalc_wine); -extern_cfg (bool, prog_edger2_wine); - -#define act(N) extern_cfg (keyseq, key_##N); +#define act(N) extern_cfg (KeySequence, key_##N); #include "actions.h" +const char* g_extProgPathFilter = +#ifdef _WIN32 + "Applications (*.exe)(*.exe);;All files (*.*)(*.*)"; +#else + ""; +#endif + // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -ConfigDialog::ConfigDialog (ForgeWindow* parent) : QDialog (parent) { +// ----------------------------------------------------------------------------- +ConfigDialog::ConfigDialog (ConfigDialog::Tab deftab, QWidget* parent, Qt::WindowFlags f) : + QDialog (parent, f) +{ + assert (g_win); ui = new Ui_ConfigUI; ui->setupUi (this); - initMainTab(); - initShortcutsTab(); - initQuickColorTab(); - initGridTab(); - initExtProgTab(); - - ui->downloadPath->setText (net_downloadpath); - ui->guessNetPaths->setChecked (net_guesspaths); - ui->autoCloseNetPrompt->setChecked (net_autoclose); - connect (ui->findDownloadPath, SIGNAL (clicked(bool)), this, SLOT (slot_findDownloadFolder())); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -ConfigDialog::~ConfigDialog() { - delete ui; -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void ConfigDialog::initMainTab() { - // Init color stuff + // Interface tab setButtonBackground (ui->backgroundColorButton, gl_bgcolor); connect (ui->backgroundColorButton, SIGNAL (clicked()), this, SLOT (slot_setGLBackground())); - setButtonBackground (ui->mainColorButton, gl_maincolor.value); + setButtonBackground (ui->mainColorButton, gl_maincolor); connect (ui->mainColorButton, SIGNAL (clicked()), this, SLOT (slot_setGLForeground())); - // Sliders ui->mainColorAlpha->setValue (gl_maincolor_alpha * 10.0f); ui->lineThickness->setValue (gl_linethickness); - - // Checkboxes ui->colorizeObjects->setChecked (lv_colorize); ui->colorBFC->setChecked (gl_colorbfc); ui->blackEdges->setChecked (gl_blackedges); - // ui->scemanticInlining->setChecked (edit_schemanticinline); ui->implicitFiles->setChecked (gui_implicitfiles); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void ConfigDialog::initShortcutsTab() { + ui->m_logostuds->setChecked (gl_logostuds); + ulong i = 0; - #define act(N) addShortcut (key_##N, ACTION(N), i); #include "actions.h" @@ -132,9 +115,45 @@ connect (ui->shortcut_set, SIGNAL (clicked()), this, SLOT (slot_setShortcut())); connect (ui->shortcut_reset, SIGNAL (clicked()), this, SLOT (slot_resetShortcut())); connect (ui->shortcut_clear, SIGNAL (clicked()), this, SLOT (slot_clearShortcut())); + + quickColors = quickColorsFromConfig(); + updateQuickColorList(); + + connect (ui->quickColor_add, SIGNAL (clicked()), this, SLOT (slot_setColor())); + connect (ui->quickColor_remove, SIGNAL (clicked()), this, SLOT (slot_delColor())); + connect (ui->quickColor_edit, SIGNAL (clicked()), this, SLOT (slot_setColor())); + connect (ui->quickColor_addSep, SIGNAL (clicked()), this, SLOT (slot_addColorSeparator())); + connect (ui->quickColor_moveUp, SIGNAL (clicked()), this, SLOT (slot_moveColor())); + connect (ui->quickColor_moveDown, SIGNAL (clicked()), this, SLOT (slot_moveColor())); + connect (ui->quickColor_clear, SIGNAL (clicked()), this, SLOT (slot_clearColors())); + + ui->downloadPath->setText (net_downloadpath); + ui->guessNetPaths->setChecked (net_guesspaths); + ui->autoCloseNetPrompt->setChecked (net_autoclose); + connect (ui->findDownloadPath, SIGNAL (clicked(bool)), this, SLOT (slot_findDownloadFolder())); + + ui->m_profileName->setText (ld_defaultname); + ui->m_profileUsername->setText (ld_defaultuser); + ui->m_profileLicense->setCurrentIndex (ld_defaultlicense); + ui->tabs->setCurrentIndex (deftab); + + initGrids(); + initExtProgs(); + + connect (ui->buttonBox, SIGNAL (clicked (QAbstractButton*)), + this, SLOT (buttonClicked(QAbstractButton*))); } -void ConfigDialog::addShortcut (keyseqconfig& cfg, QAction* act, ulong& i) { +// ============================================================================= +// ----------------------------------------------------------------------------- +ConfigDialog::~ConfigDialog() { + delete ui; +} + +// ============================================================================= +// Adds a shortcut entry to the list of shortcuts. +// ----------------------------------------------------------------------------- +void ConfigDialog::addShortcut (KeySequenceConfig& cfg, QAction* act, ulong& i) { ShortcutListItem* item = new ShortcutListItem; item->setIcon (act->icon()); item->setKeyConfig (&cfg); @@ -150,25 +169,9 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void ConfigDialog::initQuickColorTab() { - quickColors = quickColorsFromConfig(); - updateQuickColorList(); - - connect (ui->quickColor_add, SIGNAL (clicked()), this, SLOT (slot_setColor())); - connect (ui->quickColor_remove, SIGNAL (clicked()), this, SLOT (slot_delColor())); - connect (ui->quickColor_edit, SIGNAL (clicked()), this, SLOT (slot_setColor())); - connect (ui->quickColor_addSep, SIGNAL (clicked()), this, SLOT (slot_addColorSeparator())); - connect (ui->quickColor_moveUp, SIGNAL (clicked()), this, SLOT (slot_moveColor())); - connect (ui->quickColor_moveDown, SIGNAL (clicked()), this, SLOT (slot_moveColor())); - connect (ui->quickColor_clear, SIGNAL (clicked()), this, SLOT (slot_clearColors())); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void ConfigDialog::initGridTab() { +// Initializes the table of grid stuff +// ----------------------------------------------------------------------------- +void ConfigDialog::initGrids() { QGridLayout* gridlayout = new QGridLayout; QLabel* xlabel = new QLabel ("X"), *ylabel = new QLabel ("Y"), @@ -201,20 +204,19 @@ gridlayout->addWidget (dsb_gridData[i][j], i + 1, j + 1); } } - + ui->grids->setLayout (gridlayout); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static const struct extProgInfo { const str name, iconname; - strconfig* const path; + StringConfig* const path; mutable QLineEdit* input; mutable QPushButton* setPathButton; #ifndef _WIN32 - boolconfig* const wine; + BoolConfig* const wine; mutable QCheckBox* wineBox; #endif // _WIN32 } g_extProgInfo[] = { @@ -232,7 +234,10 @@ #undef EXTPROG }; -void ConfigDialog::initExtProgTab() { +// ============================================================================= +// Initializes the stuff in the ext programs tab +// ----------------------------------------------------------------------------- +void ConfigDialog::initExtProgs() { QGridLayout* pathsLayout = new QGridLayout; ulong row = 0; @@ -264,13 +269,80 @@ ++row; } - + ui->extProgs->setLayout (pathsLayout); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// Set the settings based on widget data. +// ----------------------------------------------------------------------------- +void ConfigDialog::applySettings() { + // Apply configuration + lv_colorize = ui->colorizeObjects->isChecked(); + gl_colorbfc = ui->colorBFC->isChecked(); + gl_blackedges = ui->blackEdges->isChecked(); + gl_maincolor_alpha = ((double) ui->mainColorAlpha->value()) / 10.0f; + gl_linethickness = ui->lineThickness->value(); + gui_implicitfiles = ui->implicitFiles->isChecked(); + net_downloadpath = ui->downloadPath->text(); + net_guesspaths = ui->guessNetPaths->isChecked(); + net_autoclose = ui->autoCloseNetPrompt->isChecked(); + gl_logostuds = ui->m_logostuds->isChecked(); + ld_defaultuser = ui->m_profileUsername->text(); + ld_defaultname = ui->m_profileName->text(); + ld_defaultlicense = ui->m_profileLicense->currentIndex(); + + // Rebuild the quick color toolbar + g_win->setQuickColors (quickColors); + gui_colortoolbar = quickColorString(); + + // Set the grid settings + for (int i = 0; i < g_NumGrids; ++i) + for (int j = 0; j < 4; ++j) + g_GridInfo[i].confs[j]->value = dsb_gridData[i][j]->value(); + + // Apply key shortcuts +#define act(N) ACTION(N)->setShortcut (key_##N); +#include "actions.h" + + // Ext program settings + for (const extProgInfo & info : g_extProgInfo) { + *info.path = info.input->text(); + +#ifndef _WIN32 + *info.wine = info.wineBox->isChecked(); +#endif // _WIN32 + } + + Config::save(); + reloadAllSubfiles(); + loadLogoedStuds(); + g_win->R()->setBackground(); + g_win->fullRefresh(); + g_win->updateToolBars(); + g_win->updateFileList(); +} + // ============================================================================= +// A dialog button was clicked +// ----------------------------------------------------------------------------- +void ConfigDialog::buttonClicked (QAbstractButton* button) { + typedef QDialogButtonBox QDDB; + QDialogButtonBox* dbb = ui->buttonBox; + + if (button == dbb->button (QDDB::Ok)) { + applySettings(); + accept(); + } elif (button == dbb->button (QDDB::Apply)) { + applySettings(); + } elif (button == dbb->button (QDDB::Cancel)) { + reject(); + } +} + +// ============================================================================= +// Update the list of color toolbar items in the quick color tab. +// ----------------------------------------------------------------------------- void ConfigDialog::updateQuickColorList (LDQuickColor* sel) { for (QListWidgetItem* item : quickColorItems) delete item; @@ -281,11 +353,11 @@ for (LDQuickColor& entry : quickColors) { QListWidgetItem* item = new QListWidgetItem; - if (entry.isSeparator) { + if (entry.isSeparator()) { item->setText ("--------"); item->setIcon (getIcon ("empty")); } else { - LDColor* col = entry.col; + LDColor* col = entry.color(); if (col == null) { item->setText ("[[unknown color]]"); @@ -307,8 +379,8 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// Quick colors: add or edit button was clicked. +// ----------------------------------------------------------------------------- void ConfigDialog::slot_setColor() { LDQuickColor* entry = null; QListWidgetItem* item = null; @@ -323,20 +395,20 @@ ulong i = getItemRow (item, quickColorItems); entry = &quickColors[i]; - if (entry->isSeparator == true) + if (entry->isSeparator() == true) return; // don't color separators } - short defval = entry ? entry->col->index : -1; + short defval = entry ? entry->color()->index : -1; short val; if (ColorSelector::getColor (val, defval, this) == false) return; if (entry) - entry->col = getColor (val); + entry->setColor (getColor (val)); else { - LDQuickColor entry = {getColor (val), null, false}; + LDQuickColor entry (getColor (val), null); item = getSelectedQuickColor(); ulong idx; @@ -354,8 +426,8 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// Remove a quick color +// ----------------------------------------------------------------------------- void ConfigDialog::slot_delColor() { if (ui->quickColorList->selectedItems().size() == 0) return; @@ -366,6 +438,8 @@ } // ============================================================================= +// Move a quick color up/down +// ----------------------------------------------------------------------------- void ConfigDialog::slot_moveColor() { const bool up = (static_cast<QPushButton*> (sender()) == ui->quickColor_moveUp); @@ -387,21 +461,25 @@ } // ============================================================================= +// Add a separator to quick colors +// ----------------------------------------------------------------------------- void ConfigDialog::slot_addColorSeparator() { - quickColors << LDQuickColor ({null, null, true}); + quickColors << LDQuickColor::getSeparator(); updateQuickColorList (&quickColors[quickColors.size() - 1]); } // ============================================================================= +// Clear all quick colors +// ----------------------------------------------------------------------------- void ConfigDialog::slot_clearColors() { quickColors.clear(); updateQuickColorList(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void ConfigDialog::pickColor (strconfig& conf, QPushButton* button) { +// Pick a color and set the appropriate configuration option. +// ----------------------------------------------------------------------------- +void ConfigDialog::pickColor (StringConfig& conf, QPushButton* button) { QColor col = QColorDialog::getColor (QColor (conf)); if (col.isValid()) { @@ -413,17 +491,21 @@ } } +// ============================================================================= +// ----------------------------------------------------------------------------- void ConfigDialog::slot_setGLBackground() { pickColor (gl_bgcolor, ui->backgroundColorButton); } +// ============================================================================= +// ----------------------------------------------------------------------------- void ConfigDialog::slot_setGLForeground() { pickColor (gl_maincolor, ui->mainColorButton); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// Sets background color of a given button. +// ----------------------------------------------------------------------------- void ConfigDialog::setButtonBackground (QPushButton* button, str value) { button->setIcon (getIcon ("colorselect")); button->setAutoFillBackground (true); @@ -431,6 +513,8 @@ } // ============================================================================= +// Finds the given list widget item in the list of widget items given. +// ----------------------------------------------------------------------------- int ConfigDialog::getItemRow (QListWidgetItem* item, List<QListWidgetItem*>& haystack) { int i = 0; @@ -444,16 +528,19 @@ } // ============================================================================= +// Which quick color is currently selected? +// ----------------------------------------------------------------------------- QListWidgetItem* ConfigDialog::getSelectedQuickColor() { if (ui->quickColorList->selectedItems().size() == 0) return null; - return ui->quickColorList->selectedItems() [0]; + return ui->quickColorList->selectedItems()[0]; } // ============================================================================= -QList<ShortcutListItem*> ConfigDialog::getShortcutSelection() -{ +// Get the list of shortcuts selected +// ----------------------------------------------------------------------------- +QList<ShortcutListItem*> ConfigDialog::getShortcutSelection() { QList<ShortcutListItem*> out; for (QListWidgetItem* entry : ui->shortcutsList->selectedItems()) @@ -463,8 +550,9 @@ } // ============================================================================= -void ConfigDialog::slot_setShortcut() -{ +// Edit the shortcut of a given action. +// ----------------------------------------------------------------------------- +void ConfigDialog::slot_setShortcut() { QList<ShortcutListItem*> sel = getShortcutSelection(); if (sel.size() < 1) @@ -477,8 +565,9 @@ } // ============================================================================= -void ConfigDialog::slot_resetShortcut() -{ +// Reset a shortcut to defaults +// ----------------------------------------------------------------------------- +void ConfigDialog::slot_resetShortcut() { QList<ShortcutListItem*> sel = getShortcutSelection(); for (ShortcutListItem* item : sel) { @@ -488,6 +577,8 @@ } // ============================================================================= +// Remove the shortcut of an action. +// ----------------------------------------------------------------------------- void ConfigDialog::slot_clearShortcut() { QList<ShortcutListItem*> sel = getShortcutSelection(); @@ -498,6 +589,8 @@ } // ============================================================================= +// Set the path of an external program +// ----------------------------------------------------------------------------- void ConfigDialog::slot_setExtProgPath() { const extProgInfo* info = null; @@ -509,21 +602,16 @@ } assert (info != null); - - str filter; -#ifdef _WIN32 - filter = "Applications (*.exe)(*.exe);;All files (*.*)(*.*)"; -#endif // WIN32 + str fpath = QFileDialog::getOpenFileName (this, fmt ("Path to %1", info->name), *info->path, g_extProgPathFilter); - str fpath = QFileDialog::getOpenFileName (this, fmt ("Path to %1", info->name), *info->path, filter); - - if (fpath.length() == 0) + if (fpath.isEmpty()) return; - + info->input->setText (fpath); } // ============================================================================= +// '...' button pressed for the download path // ----------------------------------------------------------------------------- void ConfigDialog::slot_findDownloadFolder() { str dpath = QFileDialog::getExistingDirectory(); @@ -531,8 +619,8 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// Updates the text string for a given shortcut list item +// ----------------------------------------------------------------------------- void ConfigDialog::setShortcutText (ShortcutListItem* item) { QAction* act = item->action(); str label = act->iconText(); @@ -541,85 +629,24 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// Gets the configuration string of the quick color toolbar +// ----------------------------------------------------------------------------- str ConfigDialog::quickColorString() { str val; - for (LDQuickColor entry : quickColors) { + for (const LDQuickColor& entry : quickColors) { if (val.length() > 0) val += ':'; - if (entry.isSeparator) + if (entry.isSeparator()) val += '|'; else - val += fmt ("%1", entry.col->index); + val += fmt ("%1", entry.color()->index); } return val; } -const Ui_ConfigUI* ConfigDialog::getUI() const { - return ui; -} - -float ConfigDialog::getGridValue (int i, int j) const { - return dsb_gridData[i][j]->value(); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void ConfigDialog::staticDialog() { - ConfigDialog dlg (g_win); - - if (dlg.exec()) { - // Apply configuration - lv_colorize = dlg.getUI()->colorizeObjects->isChecked(); - gl_colorbfc = dlg.getUI()->colorBFC->isChecked(); - // edit_schemanticinline = dlg.getUI()->scemanticInlining->isChecked(); - gl_blackedges = dlg.getUI()->blackEdges->isChecked(); - gl_maincolor_alpha = ((double) dlg.getUI()->mainColorAlpha->value()) / 10.0f; - gl_linethickness = dlg.getUI()->lineThickness->value(); - gui_implicitfiles = dlg.getUI()->implicitFiles->isChecked(); - net_downloadpath = dlg.getUI()->downloadPath->text(); - net_guesspaths = dlg.getUI()->guessNetPaths->isChecked(); - net_autoclose = dlg.getUI()->autoCloseNetPrompt->isChecked(); - - if (net_downloadpath.value.right (1) != DIRSLASH) - net_downloadpath += DIRSLASH; - - // Rebuild the quick color toolbar - g_win->setQuickColors (dlg.quickColors); - gui_colortoolbar = dlg.quickColorString(); - - // Set the grid settings - for (int i = 0; i < g_NumGrids; ++i) - for (int j = 0; j < 4; ++j) - g_GridInfo[i].confs[j]->value = dlg.getGridValue (i, j); - - // Apply key shortcuts -#define act(N) ACTION(N)->setShortcut (key_##N); -#include "actions.h" - - // Ext program settings - for (const extProgInfo & info : g_extProgInfo) { - *info.path = info.input->text(); - -#ifndef _WIN32 - *info.wine = info.wineBox->isChecked(); -#endif // _WIN32 - } - - config::save(); - reloadAllSubfiles(); - g_win->R()->setBackground(); - g_win->fullRefresh(); - g_win->updateToolBars(); - g_win->updateFileList(); - } -} - // ========================================================================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ========================================================================================================================= @@ -645,9 +672,8 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -bool KeySequenceDialog::staticDialog (keyseqconfig* cfg, QWidget* parent) { +// ----------------------------------------------------------------------------- +bool KeySequenceDialog::staticDialog (KeySequenceConfig* cfg, QWidget* parent) { KeySequenceDialog dlg (cfg->value, parent); if (dlg.exec() == false) @@ -658,8 +684,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void KeySequenceDialog::updateOutput() { str shortcut = seq.toString(); @@ -671,11 +696,8 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void KeySequenceDialog::keyPressEvent (QKeyEvent* ev) { seq = ev->key() + ev->modifiers(); updateOutput(); -} - -#include "build/moc_configDialog.cpp" \ No newline at end of file +} \ No newline at end of file
--- a/src/configDialog.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/configDialog.h Sat Sep 07 13:23:09 2013 +0300 @@ -28,7 +28,7 @@ // ============================================================================= class ShortcutListItem : public QListWidgetItem { - PROPERTY (keyseqconfig*, keyConfig, setKeyConfig) + PROPERTY (KeySequenceConfig*, keyConfig, setKeyConfig) PROPERTY (QAction*, action, setAction) public: @@ -41,10 +41,18 @@ Q_OBJECT public: - ConfigDialog (ForgeWindow* parent); + enum Tab { + InterfaceTab, + ProfileTab, + ShortcutsTab, + QuickColorsTab, + GridsTab, + ExtProgsTab, + DownloadTab + }; + + explicit ConfigDialog (Tab deftab = InterfaceTab, QWidget* parent = null, Qt::WindowFlags f = 0); virtual ~ConfigDialog(); - static void staticDialog(); - const Ui_ConfigUI* getUI() const; float getGridValue (int i, int j) const; List<LDQuickColor> quickColors; @@ -56,20 +64,18 @@ QLabel* lb_gridIcons[3]; List<QListWidgetItem*> quickColorItems; - void initMainTab(); - void initShortcutsTab(); - void initQuickColorTab(); - void initGridTab(); - void initExtProgTab(); - void addShortcut (keyseqconfig& cfg, QAction* act, ulong& i); + void applySettings(); + void addShortcut (KeySequenceConfig& cfg, QAction* act, ulong& i); void setButtonBackground (QPushButton* button, str value); - void pickColor (strconfig& cfg, QPushButton* button); + void pickColor (StringConfig& cfg, QPushButton* button); void updateQuickColorList (LDQuickColor* sel = null); void setShortcutText (ShortcutListItem* item); int getItemRow (QListWidgetItem* item, List<QListWidgetItem*>& haystack); str quickColorString(); QListWidgetItem* getSelectedQuickColor(); QList<ShortcutListItem*> getShortcutSelection(); + void initGrids(); + void initExtProgs(); private slots: void slot_setGLBackground(); @@ -84,6 +90,7 @@ void slot_clearColors(); void slot_setExtProgPath(); void slot_findDownloadFolder(); + void buttonClicked (QAbstractButton* button); }; // ============================================================================= @@ -94,7 +101,7 @@ public: explicit KeySequenceDialog (QKeySequence seq, QWidget* parent = null, Qt::WindowFlags f = 0); - static bool staticDialog (keyseqconfig* cfg, QWidget* parent = null); + static bool staticDialog (KeySequenceConfig* cfg, QWidget* parent = null); QLabel* lb_output; QDialogButtonBox* bbx_buttons;
--- a/src/dialogs.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/dialogs.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -27,6 +27,8 @@ #include <QGridLayout> #include <QProgressBar> #include <QCheckBox> +#include <QDesktopServices> +#include <QUrl> #include "dialogs.h" #include "widgets.h" @@ -38,10 +40,14 @@ #include "ui_overlay.h" #include "ui_ldrawpath.h" #include "ui_openprogress.h" +#include "ui_extprogpath.h" +#include "ui_about.h" -extern_cfg (str, io_ldpath); +extern const char* g_extProgPathFilter; +extern_cfg (String, io_ldpath); // ============================================================================= +// ----------------------------------------------------------------------------- OverlayDialog::OverlayDialog (QWidget* parent, Qt::WindowFlags f) : QDialog (parent, f) { ui = new Ui_OverlayUI; ui->setupUi (this); @@ -69,10 +75,14 @@ fillDefaults (cam); } +// ============================================================================= +// ----------------------------------------------------------------------------- OverlayDialog::~OverlayDialog() { delete ui; } +// ============================================================================= +// ----------------------------------------------------------------------------- void OverlayDialog::fillDefaults (int newcam) { overlayMeta& info = g_win->R()->getOverlay (newcam); radioDefault<int> (newcam, m_cameraArgs); @@ -92,6 +102,8 @@ } } +// ============================================================================= +// ----------------------------------------------------------------------------- str OverlayDialog::fpath() const { return ui->filename->text(); } @@ -129,11 +141,12 @@ ui->buttonBox->button (QDialogButtonBox::Ok)->setEnabled (enable); } -// ================================================================================================= +// ============================================================================= +// ----------------------------------------------------------------------------- LDrawPathDialog::LDrawPathDialog (const bool validDefault, QWidget* parent, Qt::WindowFlags f) : QDialog (parent, f), - m_validDefault (validDefault) { - + m_validDefault (validDefault) +{ ui = new Ui_LDPathUI; ui->setupUi (this); ui->status->setText ("---"); @@ -158,6 +171,8 @@ slot_tryConfigure(); } +// ============================================================================= +// ----------------------------------------------------------------------------- LDrawPathDialog::~LDrawPathDialog() { delete ui; } @@ -178,6 +193,8 @@ return ui->path->text(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void LDrawPathDialog::slot_findPath() { str newpath = QFileDialog::getExistingDirectory (this, "Find LDraw Path"); @@ -187,29 +204,34 @@ } } +// ============================================================================= +// ----------------------------------------------------------------------------- void LDrawPathDialog::slot_exit() { exit (1); } +// ============================================================================= +// ----------------------------------------------------------------------------- void LDrawPathDialog::slot_tryConfigure() { if (LDPaths::tryConfigure (filename()) == false) { ui->status->setText (fmt ("<span style=\"color:#700; \">%1</span>", LDPaths::getError())); okButton()->setEnabled (false); return; } - + ui->status->setText ("<span style=\"color: #270; \">OK!</span>"); okButton()->setEnabled (true); } +// ============================================================================= +// ----------------------------------------------------------------------------- void LDrawPathDialog::slot_accept() { - config::save(); + Config::save(); accept(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- OpenProgressDialog::OpenProgressDialog (QWidget* parent, Qt::WindowFlags f) : QDialog (parent, f) { ui = new Ui_OpenProgressUI; ui->setupUi (this); @@ -219,29 +241,96 @@ m_progress = 0; } +// ============================================================================= +// ----------------------------------------------------------------------------- OpenProgressDialog::~OpenProgressDialog() { delete ui; } +// ============================================================================= +// ----------------------------------------------------------------------------- READ_ACCESSOR (ulong, OpenProgressDialog::numLines) { return m_numLines; } +// ============================================================================= +// ----------------------------------------------------------------------------- SET_ACCESSOR (ulong, OpenProgressDialog::setNumLines) { m_numLines = val; ui->progressBar->setRange (0, numLines()); updateValues(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void OpenProgressDialog::updateValues() { ui->progressText->setText (fmt ("Parsing... %1 / %2", progress(), numLines())); ui->progressBar->setValue (progress()); } +// ============================================================================= +// ----------------------------------------------------------------------------- void OpenProgressDialog::updateProgress (int progress) { m_progress = progress; updateValues(); } -#include "build/moc_dialogs.cpp" -// kate: indent-mode cstyle; indent-width 4; replace-tabs off; tab-width 4; +// ============================================================================= +// ----------------------------------------------------------------------------- +ExtProgPathPrompt::ExtProgPathPrompt (str progName, QWidget* parent, Qt::WindowFlags f) : + QDialog (parent, f), + ui (new Ui_ExtProgPath) +{ + ui->setupUi (this); + + str labelText = ui->m_label->text(); + labelText.replace ("<PROGRAM>", progName); + ui->m_label->setText (labelText); + + connect (ui->m_findPath, SIGNAL (clicked (bool)), this, SLOT (findPath())); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +ExtProgPathPrompt::~ExtProgPathPrompt() { + delete ui; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void ExtProgPathPrompt::findPath() { + str path = QFileDialog::getOpenFileName (null, "", "", g_extProgPathFilter); + + if (!path.isEmpty()) + ui->m_path->setText (path); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +str ExtProgPathPrompt::getPath() const { + return ui->m_path->text(); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +AboutDialog::AboutDialog (QWidget* parent, Qt::WindowFlags f) : + QDialog (parent, f) +{ + Ui::AboutUI ui; + ui.setupUi (this); + ui.versionInfo->setText (fmt (tr ("LDForge %1"), fullVersionString())); + + QPushButton* mailButton = new QPushButton; + mailButton->setText ("Contact"); + mailButton->setIcon (getIcon ("mail")); + ui.buttonBox->addButton (static_cast<QAbstractButton*> (mailButton), QDialogButtonBox::HelpRole); + connect (ui.buttonBox, SIGNAL (helpRequested()), this, SLOT (slot_mail())); + + setWindowTitle ("About " APPNAME); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void AboutDialog::slot_mail() { + QDesktopServices::openUrl (QUrl ("mailto:Santeri Piippo <slatenails64@gmail.com>?subject=LDForge")); +} \ No newline at end of file
--- a/src/dialogs.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/dialogs.h Sat Sep 07 13:23:09 2013 +0300 @@ -23,6 +23,7 @@ #include "common.h" #include "types.h" +class Ui_ExtProgPath; class QRadioButton; class QCheckBox; class QProgressBar; @@ -32,7 +33,7 @@ class QPushButton; class QLineEdit; class QSpinBox; -class RadioBox; +class RadioGroup; class QLabel; class QAbstractButton; class Ui_OverlayUI; @@ -107,5 +108,31 @@ void updateValues(); }; -#endif // DIALOGS_H -// kate: indent-mode cstyle; indent-width 4; replace-tabs off; tab-width 4; +// ============================================================================= +class ExtProgPathPrompt : public QDialog { + Q_OBJECT + +public: + explicit ExtProgPathPrompt (str progName, QWidget* parent = 0, Qt::WindowFlags f = 0); + virtual ~ExtProgPathPrompt(); + str getPath() const; + +public slots: + void findPath(); + +private: + Ui_ExtProgPath* ui; +}; + +// ============================================================================= +class AboutDialog : public QDialog { + Q_OBJECT + +public: + AboutDialog (QWidget* parent = null, Qt::WindowFlags f = 0); + +private slots: + void slot_mail(); +}; + +#endif // DIALOGS_H \ No newline at end of file
--- a/src/docs.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/docs.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -23,6 +23,8 @@ #include "common.h" #include "types.h" +// ============================================================================= +// ----------------------------------------------------------------------------- class DocumentViewer : public QDialog { public: explicit DocumentViewer (QWidget* parent = null, Qt::WindowFlags f = 0) : QDialog (parent, f) { @@ -61,6 +63,8 @@ "<p>Finally, use the \"Set Overlay Image\" dialog and fill in the details. The " "overlay image should then be ready for use."; +// ============================================================================= +// ----------------------------------------------------------------------------- void showDocumentation (const char* text) { DocumentViewer dlg; dlg.setText (text);
--- a/src/docs.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/docs.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */
--- a/src/download.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/download.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -26,13 +26,13 @@ #include "ui_downloadfrom.h" #include "types.h" #include "gui.h" -#include "build/moc_download.cpp" #include "file.h" #include "gldraw.h" +#include "configDialog.h" -cfg (str, net_downloadpath, ""); -cfg (bool, net_guesspaths, true); -cfg (bool, net_autoclose, false); +cfg (String, net_downloadpath, ""); +cfg (Bool, net_guesspaths, true); +cfg (Bool, net_autoclose, false); constexpr const char* PartDownloader::k_OfficialURL, *PartDownloader::k_UnofficialURL; @@ -44,6 +44,8 @@ if (path == "" || QDir (path).exists() == false) { critical (PartDownloader::tr ("You need to specify a valid path for " "downloaded files in the configuration to download paths.")); + + (new ConfigDialog (ConfigDialog::DownloadTab, null))->exec(); return; } @@ -73,7 +75,7 @@ m_downloadButton = new QPushButton (tr ("Download")); ui->buttonBox->addButton (m_downloadButton, QDialogButtonBox::ActionRole); - ui->buttonBox->button (QDialogButtonBox::Abort)->setEnabled (false); + getButton (Abort)->setEnabled (false); connect (ui->source, SIGNAL (currentIndexChanged (int)), this, SLOT (sourceChanged (int))); connect (ui->buttonBox, SIGNAL (clicked (QAbstractButton*)), this, SLOT (buttonClicked (QAbstractButton*))); @@ -116,8 +118,8 @@ // Ensure .dat extension if (dest.right (4) != ".dat") { - // Remove the existing extension, if any. It may be we're here over a - // typo in the .dat extension. + /* Remove the existing extension, if any. It may be we're here over a + typo in the .dat extension. */ const int dotpos = dest.lastIndexOf ("."); if (dotpos != -1 && dotpos >= dest.length() - 4) dest.chop (dest.length() - dotpos); @@ -125,8 +127,8 @@ dest += ".dat"; } - // If the part starts with s\ or s/, then use parts/s/. Same goes with - // 48\ and p/48/. + /* If the part starts with s\ or s/, then use parts/s/. Same goes with + 48\ and p/48/. */ if (dest.left (2) == "s\\" || dest.left (2) == "s/") { dest.remove (0, 2); dest.prepend ("parts/s/"); @@ -136,31 +138,30 @@ } /* Try determine where to put this part. We have four directories: - * parts/, parts/s/, p/, and p/48/. If we haven't already specified - * either parts/ or p/, we need to add it automatically. Part files - * are numbers which can be followed by: - * - c** (composites) - * - d** (formed stickers) - * - a lowercase alphabetic letter for variants - * - * Subfiles have an s** prefix, in which case we use parts/s/. Note that - * the regex starts with a '^' so it won't catch already fully given part - * file names. - */ - { - str partRegex = "^u?[0-9]+(c[0-9][0-9]+)*(d[0-9][0-9]+)*[a-z]?(p[0-9a-z][0-9a-z]+)*"; - str subpartRegex = partRegex + "s[0-9][0-9]+"; - - partRegex += "\\.dat$"; - subpartRegex += "\\.dat$"; - - if (QRegExp (subpartRegex).exactMatch (dest)) - dest.prepend ("parts/s/"); - elif (QRegExp (partRegex).exactMatch (dest)) - dest.prepend ("parts/"); - elif (dest.left (6) != "parts/" && dest.left (2) != "p/") - dest.prepend ("p/"); - } + parts/, parts/s/, p/, and p/48/. If we haven't already specified + either parts/ or p/, we need to add it automatically. Part files + are numbers wit a possible u prefix for parts with unknown number + which can be followed by any of: + - c** (composites) + - d** (formed stickers) + - p** (patterns) + - a lowercase alphabetic letter for variants + + Subfiles (usually) have an s** prefix, in which case we use parts/s/. + Note that the regex starts with a '^' so it won't catch already fully + given part file names. */ + str partRegex = "^u?[0-9]+(c[0-9][0-9]+)*(d[0-9][0-9]+)*[a-z]?(p[0-9a-z][0-9a-z]+)*"; + str subpartRegex = partRegex + "s[0-9][0-9]+"; + + partRegex += "\\.dat$"; + subpartRegex += "\\.dat$"; + + if (QRegExp (subpartRegex).exactMatch (dest)) + dest.prepend ("parts/s/"); + elif (QRegExp (partRegex).exactMatch (dest)) + dest.prepend ("parts/"); + elif (dest.left (6) != "parts/" && dest.left (2) != "p/") + dest.prepend ("p/"); } // ============================================================================= @@ -178,6 +179,8 @@ ui->fileNameLabel->setText (tr ("File name:")); } +// ============================================================================= +// ----------------------------------------------------------------------------- void PartDownloader::buttonClicked (QAbstractButton* btn) { if (btn == getButton (Close)) { reject(); @@ -196,7 +199,7 @@ modifyDest (dest); - if (QFile::exists (PartDownloader::getDownloadPath() + dest)) { + if (QFile::exists (PartDownloader::getDownloadPath() + DIRSLASH + dest)) { const str overwritemsg = fmt (tr ("%1 already exists in download directory. Overwrite?"), dest); if (!confirm (tr ("Overwrite?"), overwritemsg)) @@ -224,7 +227,7 @@ return; modifyDest (dest); - print ("DOWNLOAD: %1 -> %2\n", url, PartDownloader::getDownloadPath() + dest); + print ("DOWNLOAD: %1 -> %2\n", url, PartDownloader::getDownloadPath() + DIRSLASH + dest); PartDownloadRequest* req = new PartDownloadRequest (url, dest, primary, this); m_filesToDownload << dest; @@ -260,7 +263,7 @@ g_win->fullRefresh(); g_win->R()->resetAngles(); } - + if (net_autoclose && !failed) { // Close automatically if desired. accept(); @@ -298,7 +301,7 @@ m_prompt (parent), m_url (url), m_dest (dest), - m_fpath (PartDownloader::getDownloadPath() + dest), + m_fpath (PartDownloader::getDownloadPath() + DIRSLASH + dest), m_nam (new QNetworkAccessManager), m_firstUpdate (true), m_state (Requesting), @@ -410,12 +413,9 @@ // from unknown file references, try resolve that by downloading the reference. // This is why downloading a part may end up downloading multiple files, as // it resolves dependencies. - for (LDObject* obj : *f) { - if (obj->getType() != LDObject::Error) - continue; - - LDErrorObject* err = static_cast<LDErrorObject*> (obj); - if (err->fileRef() == "") + for (LDObject* obj : f->objects()) { + LDError* err = dynamic_cast<LDError*> (obj); + if (!err || err->fileRef().isEmpty()) continue; str dest = err->fileRef(); @@ -423,8 +423,10 @@ m_prompt->downloadFile (dest, str (PartDownloader::k_UnofficialURL) + dest, false); } - if (m_primary) + if (m_primary) { + addRecentFile (m_fpath); m_prompt->setPrimaryFile (f); + } m_prompt->checkIfFinished(); }
--- a/src/download.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/download.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */
--- a/src/extprogs.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/extprogs.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -31,13 +31,13 @@ #include "file.h" #include "widgets.h" #include "history.h" -#include "labeledwidget.h" #include "ui_ytruder.h" #include "ui_intersector.h" #include "ui_rectifier.h" #include "ui_coverer.h" #include "ui_isecalc.h" #include "ui_edger2.h" +#include "dialogs.h" enum extprog { Isecalc, @@ -49,22 +49,32 @@ }; // ============================================================================= -cfg (str, prog_isecalc, ""); -cfg (str, prog_intersector, ""); -cfg (str, prog_coverer, ""); -cfg (str, prog_ytruder, ""); -cfg (str, prog_rectifier, ""); -cfg (str, prog_edger2, ""); +// ----------------------------------------------------------------------------- +cfg (String, prog_isecalc, ""); +cfg (String, prog_intersector, ""); +cfg (String, prog_coverer, ""); +cfg (String, prog_ytruder, ""); +cfg (String, prog_rectifier, ""); +cfg (String, prog_edger2, ""); + +StringConfig* const g_extProgPaths[] = { + &prog_isecalc, + &prog_intersector, + &prog_coverer, + &prog_ytruder, + &prog_rectifier, + &prog_edger2, +}; #ifndef _WIN32 -cfg (bool, prog_isecalc_wine, false); -cfg (bool, prog_intersector_wine, false); -cfg (bool, prog_coverer_wine, false); -cfg (bool, prog_ytruder_wine, false); -cfg (bool, prog_rectifier_wine, false); -cfg (bool, prog_edger2_wine, false); +cfg (Bool, prog_isecalc_wine, false); +cfg (Bool, prog_intersector_wine, false); +cfg (Bool, prog_coverer_wine, false); +cfg (Bool, prog_ytruder_wine, false); +cfg (Bool, prog_rectifier_wine, false); +cfg (Bool, prog_edger2_wine, false); -boolconfig* const g_extProgWine[] = { +BoolConfig* const g_extProgWine[] = { &prog_isecalc_wine, &prog_intersector_wine, &prog_coverer_wine, @@ -84,19 +94,24 @@ }; // ============================================================================= -static bool checkProgPath (str path, const extprog prog) { +// ----------------------------------------------------------------------------- +static bool checkProgPath (const extprog prog) { + alias path = g_extProgPaths[prog]->value; + if (path.length() > 0) return true; - const char* name = g_extProgNames[prog]; + ExtProgPathPrompt* dlg = new ExtProgPathPrompt (g_extProgNames[prog]); + if (dlg->exec() && !dlg->getPath().isEmpty()) { + path = dlg->getPath(); + return true; + } - critical (fmt (QObject::tr ("Couldn't run %1 as no path has " - "been defined for it. Use the configuration dialog's External Programs " - "tab to define a path for %1."), name)); return false; } // ============================================================================= +// ----------------------------------------------------------------------------- static str processErrorString (QProcess& proc) { switch (proc.error()) { case QProcess::FailedToStart: @@ -120,6 +135,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- static bool mkTempFile (QTemporaryFile& tmp, str& fname) { if (!tmp.open()) return false; @@ -130,10 +146,12 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void writeObjects (List<LDObject*>& objects, File& f) { for (LDObject* obj : objects) { if (obj->getType() == LDObject::Subfile) { - List<LDObject*> objs = static_cast<LDSubfileObject*> (obj)->inlineContents (true, false); + LDSubfile* ref = static_cast<LDSubfile*> (obj); + List<LDObject*> objs = ref->inlineContents (LDSubfile::DeepInline); writeObjects (objs, f); @@ -144,6 +162,8 @@ } } +// ============================================================================= +// ----------------------------------------------------------------------------- void writeObjects (List<LDObject*>& objects, str fname) { // Write the input file File f (fname, File::Write); @@ -158,15 +178,17 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void writeSelection (str fname) { writeObjects (g_win->sel(), fname); } // ============================================================================= +// ----------------------------------------------------------------------------- void writeColorGroup (const short colnum, str fname) { List<LDObject*> objects; - for (LDObject* obj : *LDFile::current()) { + for (LDObject* obj : LDFile::current()->objects()) { if (obj->isColored() == false || obj->color() != colnum) continue; @@ -177,6 +199,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- bool runUtilityProcess (extprog prog, str path, str argvstr) { QTemporaryFile input, output; str inputname, outputname; @@ -231,7 +254,8 @@ return true; } -// ================================================================================================ +// ============================================================================= +// ----------------------------------------------------------------------------- static void insertOutput (str fname, bool replace, List<short> colorsToReplace) { #ifndef RELEASE QFile::copy (fname, "./debug_lastOutput"); @@ -271,13 +295,12 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= // Interface for Ytruder +// ----------------------------------------------------------------------------- DEFINE_ACTION (Ytruder, 0) { setlocale (LC_ALL, "C"); - if (!checkProgPath (prog_ytruder, Ytruder)) + if (!checkProgPath (Ytruder)) return; QDialog* dlg = new QDialog; @@ -327,13 +350,12 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= // Rectifier interface +// ----------------------------------------------------------------------------- DEFINE_ACTION (Rectifier, 0){ setlocale (LC_ALL, "C"); - if (!checkProgPath (prog_rectifier, Rectifier)) + if (!checkProgPath (Rectifier)) return; QDialog* dlg = new QDialog; @@ -370,20 +392,13 @@ insertOutput (outDATName, true, {}); } -LabeledWidget<QComboBox>* buildColorSelector (const char* label) { - LabeledWidget<QComboBox>* widget = new LabeledWidget<QComboBox> (label, new QComboBox); - makeColorSelector (widget->w()); - return widget; -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= // Intersector interface +// ----------------------------------------------------------------------------- DEFINE_ACTION (Intersector, 0) { setlocale (LC_ALL, "C"); - if (!checkProgPath (prog_intersector, Intersector)) + if (!checkProgPath (Intersector)) return; QDialog* dlg = new QDialog; @@ -461,20 +476,20 @@ if (repeatInverse && runUtilityProcess (Intersector, prog_intersector, argv_inverse)) insertOutput (outDAT2Name, false, {cutCol}); - if (ui.cb_edges->isChecked() && runUtilityProcess (Isecalc, prog_isecalc, - join ({inDATName, cutDATName, edgesDATName}))) - { + if ( + ui.cb_edges->isChecked() && + checkProgPath (Isecalc) && + runUtilityProcess (Isecalc, prog_isecalc, join ({inDATName, cutDATName, edgesDATName})) + ) insertOutput (edgesDATName, false, {}); - } } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Coverer, 0) { setlocale (LC_ALL, "C"); - if (!checkProgPath (prog_coverer, Coverer)) + if (!checkProgPath (Coverer)) return; QDialog* dlg = new QDialog; @@ -525,12 +540,11 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Isecalc, 0) { setlocale (LC_ALL, "C"); - if (!checkProgPath (prog_isecalc, Isecalc)) + if (!checkProgPath (Isecalc)) return; Ui::IsecalcUI ui; @@ -577,12 +591,11 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Edger2, 0) { setlocale (LC_ALL, "C"); - if (!checkProgPath (prog_edger2, Edger2)) + if (!checkProgPath (Edger2)) return; QDialog* dlg = new QDialog;
--- a/src/file.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/file.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -14,14 +14,17 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. + * ===================================================================== + * + * file.cpp: File I/O and management. + * - File loading, parsing, manipulation, saving, closing. + * - LDraw path verification. */ #include <QMessageBox> #include <QFileDialog> #include <QDir> #include <QApplication> - -#include <stdlib.h> #include "common.h" #include "config.h" #include "file.h" @@ -31,19 +34,23 @@ #include "dialogs.h" #include "gldraw.h" -cfg (str, io_ldpath, ""); -cfg (str, io_recentfiles, ""); -extern_cfg (str, net_downloadpath); +cfg (String, io_ldpath, ""); +cfg (List, io_recentfiles, {}); +extern_cfg (String, net_downloadpath); +extern_cfg (Bool, gl_logostuds); static bool g_loadingMainFile = false; static const int g_MaxRecentFiles = 5; static bool g_aborted = false; +static LDFile* g_logoedStud = null; +static LDFile* g_logoedStud2 = null; LDFile* LDFile::m_curfile = null; DEFINE_PROPERTY (QListWidgetItem*, LDFile, listItem, setListItem) // ============================================================================= +// ----------------------------------------------------------------------------- namespace LDPaths { static str pathError; @@ -94,6 +101,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- LDFile::LDFile() { setImplicit (true); setSavePos (-1); @@ -102,13 +110,14 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- LDFile::~LDFile() { // Clear everything from the model - for (LDObject* obj : m_objs) + for (LDObject* obj : objects()) delete obj; // Clear the cache as well - for (LDObject* obj : m_cache) + for (LDObject* obj : cache()) delete obj; // Remove this file from the list of files @@ -123,25 +132,33 @@ // file as something else. if (this == LDFile::current()) { // If we closed the last file, create a blank one. - if (g_loadedFiles.size() == 0) + if (countExplicitFiles() == 0) newFile(); - else - LDFile::setCurrent (g_loadedFiles[0]); + else { + // Find the first explicit file loaded + int idx = 0; + while (g_loadedFiles[idx]->implicit()) + idx++; + + LDFile::setCurrent (g_loadedFiles[idx]); + } } g_win->updateFileList(); } // ============================================================================= +// ----------------------------------------------------------------------------- LDFile* findLoadedFile (str name) { for (LDFile* file : g_loadedFiles) - if (file->name() == name) + if (!file->name().isEmpty() && file->getShortName() == name) return file; return null; } // ============================================================================= +// ----------------------------------------------------------------------------- str dirname (str path) { long lastpos = path.lastIndexOf (DIRSLASH); @@ -157,6 +174,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- str basename (str path) { long lastpos = path.lastIndexOf (DIRSLASH); @@ -167,6 +185,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- File* openLDrawFile (str relpath, bool subdirs) { print ("%1: Try to open %2\n", __func__, relpath); File* f = new File; @@ -213,8 +232,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void FileLoader::start() { setDone (false); setProgress (0); @@ -223,10 +241,10 @@ if (concurrent()) { g_aborted = false; - // Show a progress dialog if we're loading the main file here and move - // the actual work to a separate thread as this can be a rather intensive - // operation and if we don't respond quickly enough, the program can be - // deemed inresponsive.. which is a bad thing. + // Show a progress dialog if we're loading the main file here so we can + // show progress updates and keep the WM posted that we're still here. + // Of course we cannot exec() the dialog because then the dialog would + // block. dlg = new OpenProgressDialog (g_win); dlg->setNumLines (lines().size()); dlg->setModal (true); @@ -238,12 +256,15 @@ } else dlg = null; + // Begin working work (0); } +// ============================================================================= +// ----------------------------------------------------------------------------- void FileLoader::work (int i) { + // User wishes to abort, so stop here now. if (aborted()) { - // We were flagged for abortion, so abort. for (LDObject* obj : m_objs) delete obj; @@ -252,6 +273,7 @@ return; } + // Parse up to 300 lines per iteration int max = i + 300; for (; i < max && i < (int) lines().size(); ++i) { @@ -267,7 +289,7 @@ // Check for parse errors and warn about tthem if (obj->getType() == LDObject::Error) { - log ("Couldn't parse line #%1: %2", m_progress + 1, static_cast<LDErrorObject*> (obj)->reason); + log ("Couldn't parse line #%1: %2", m_progress + 1, static_cast<LDError*> (obj)->reason); if (m_warningsPointer) (*m_warningsPointer)++; @@ -276,24 +298,39 @@ m_objs << obj; setProgress (i); + // If we have a dialog pointer, update the progress now if (concurrent()) dlg->updateProgress (i); } + // If we're done now, tell the environment we're done and stop. if (i >= ((int) lines().size()) - 1) { emit workDone(); setDone (true); return; } + // Otherwise, continue, by recursing back. if (!done()) { + // If we have a dialog to show progress output to, we cannot just call + // work() again immediately as the dialog needs some processor cycles as + // well. Thus, take a detour through the event loop by using the + // meta-object system. + // + // This terminates the loop here and control goes back to the function + // which called the file loader. It will keep processing the event loop + // until we're ready (see loadFileContents), thus the event loop will + // eventually catch the invokation we throw here and send us back. Though + // it's not technically recursion anymore, more like a for loop. :P if (concurrent()) - QMetaObject::invokeMethod (this, "work", Qt::QueuedConnection, Q_ARG (ulong, i + 1)); + QMetaObject::invokeMethod (this, "work", Qt::QueuedConnection, Q_ARG (int, i + 1)); else work (i + 1); } } +// ============================================================================= +// ----------------------------------------------------------------------------- void FileLoader::abort() { setAborted (true); @@ -302,8 +339,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- List<LDObject*> loadFileContents (File* f, ulong* numWarnings, bool* ok) { List<str> lines; List<LDObject*> objs; @@ -323,6 +359,10 @@ loader->setConcurrent (g_loadingMainFile); loader->start(); + // After start() returns, if the loader isn't done yet, it's delaying + // its next iteration through the event loop. We need to catch this here + // by telling the event loop to tick, which will tick the file loader again. + // We keep doing this until the file loader is ready. while (loader->done() == false) qApp->processEvents(); @@ -335,8 +375,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- LDFile* openDATFile (str path, bool search) { // Convert the file name to lowercase since some parts contain uppercase // file names. I'll assume here that the library will always use lowercase @@ -383,8 +422,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- bool LDFile::safeToClose() { typedef QMessageBox msgbox; setlocale (LC_ALL, "C"); @@ -433,8 +471,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void closeAll() { // Remove all loaded files and the objects they contain List<LDFile*> files = g_loadedFiles; @@ -443,8 +480,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void newFile() { // Create a new anonymous file and set it to our current LDFile* f = new LDFile; @@ -462,10 +498,9 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void addRecentFile (str path) { - QStringList rfiles = io_recentfiles.value.split ('@'); + alias rfiles = io_recentfiles.value; int idx = rfiles.indexOf (path); // If this file already is in the list, pop it out. @@ -484,17 +519,13 @@ // Add the file rfiles << path; - // Rebuild the config string - io_recentfiles = rfiles.join ("@"); - - config::save(); + Config::save(); g_win->updateRecentFilesMenu(); } // ============================================================================= +// Open an LDraw file and set it as the main model // ----------------------------------------------------------------------------- -// Open an LDraw file and set it as the main model -// ============================================================================= void openMainFile (str path) { g_loadingMainFile = true; LDFile* file = openDATFile (path, false); @@ -530,8 +561,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- bool LDFile::save (str savepath) { if (!savepath.length()) savepath = name(); @@ -544,11 +574,11 @@ // If the second object in the list holds the file name, update that now. // Only do this if the file is explicitly open. If it's saved into a directory // called "s" or "48", prepend that into the name. - LDCommentObject* fpathComment = null; + LDComment* fpathComment = null; LDObject* first = object (1); if (!implicit() && first != null && first->getType() == LDObject::Comment) { - fpathComment = static_cast<LDCommentObject*> (first); + fpathComment = static_cast<LDComment*> (first); if (fpathComment->text.left (6) == "Name: ") { str newname; @@ -565,7 +595,7 @@ // File is open, now save the model to it. Note that LDraw requires files to // have DOS line endings, so we terminate the lines with \r\n. - for (LDObject* obj : objs()) + for (LDObject* obj : objects()) f.write (obj->raw() + "\r\n"); // File is saved, now clean up. @@ -581,17 +611,18 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- #define CHECK_TOKEN_COUNT(N) \ if (tokens.size() != N) \ - return new LDErrorObject (line, "Bad amount of tokens"); + return new LDError (line, "Bad amount of tokens"); #define CHECK_TOKEN_NUMBERS(MIN, MAX) \ for (ushort i = MIN; i <= MAX; ++i) \ if (!isNumber (tokens[i])) \ - return new LDErrorObject (line, fmt ("Token #%1 was `%2`, expected a number", (i + 1), tokens[i])); + return new LDError (line, fmt ("Token #%1 was `%2`, expected a number", (i + 1), tokens[i])); +// ============================================================================= +// ----------------------------------------------------------------------------- static vertex parseVertex (QStringList& s, const ushort n) { vertex v; @@ -602,21 +633,20 @@ } // ============================================================================= -// ----------------------------------------------------------------------------- // This is the LDraw code parser function. It takes in a string containing LDraw // code and returns the object parsed from it. parseLine never returns null, // the object will be LDError if it could not be parsed properly. -// ============================================================================= +// ----------------------------------------------------------------------------- LDObject* parseLine (str line) { QStringList tokens = line.split (" ", str::SkipEmptyParts); if (tokens.size() <= 0) { // Line was empty, or only consisted of whitespace - return new LDEmptyObject; + return new LDEmpty; } if (tokens[0].length() != 1 || tokens[0][0].isDigit() == false) - return new LDErrorObject (line, "Illogical line code"); + return new LDError (line, "Illogical line code"); int num = tokens[0][0].digitValue(); @@ -631,25 +661,25 @@ // Handle BFC statements if (tokens.size() > 2 && tokens[1] == "BFC") { - for (short i = 0; i < LDBFCObject::NumStatements; ++i) - if (comm == fmt ("BFC %1", LDBFCObject::statements [i])) - return new LDBFCObject ((LDBFCObject::Type) i); + for (short i = 0; i < LDBFC::NumStatements; ++i) + if (comm == fmt ("BFC %1", LDBFC::statements [i])) + return new LDBFC ((LDBFC::Type) i); // MLCAD is notorious for stuffing these statements in parts it // creates. The above block only handles valid statements, so we // need to handle MLCAD-style invertnext, clip and noclip separately. struct { const char* a; - LDBFCObject::Type b; + LDBFC::Type b; } BFCData[] = { - { "INVERTNEXT", LDBFCObject::InvertNext }, - { "NOCLIP", LDBFCObject::NoClip }, - { "CLIP", LDBFCObject::Clip } + { "INVERTNEXT", LDBFC::InvertNext }, + { "NOCLIP", LDBFC::NoClip }, + { "CLIP", LDBFC::Clip } }; for (const auto& i : BFCData) if (comm == fmt ("BFC CERTIFY %1", i.a)) - return new LDBFCObject (i.b); + return new LDBFC (i.b); } if (tokens.size() > 2 && tokens[1] == "!LDFORGE") { @@ -659,7 +689,7 @@ CHECK_TOKEN_COUNT (7) CHECK_TOKEN_NUMBERS (3, 6) - LDVertexObject* obj = new LDVertexObject; + LDVertex* obj = new LDVertex; obj->setColor (tokens[3].toLong()); for (const Axis ax : g_Axes) @@ -670,7 +700,7 @@ CHECK_TOKEN_COUNT (9); CHECK_TOKEN_NUMBERS (5, 8) - LDOverlayObject* obj = new LDOverlayObject; + LDOverlay* obj = new LDOverlay; obj->setFilename (tokens[3]); obj->setCamera (tokens[4].toLong()); obj->setX (tokens[5].toLong()); @@ -682,7 +712,7 @@ } // Just a regular comment: - LDCommentObject* obj = new LDCommentObject; + LDComment* obj = new LDComment; obj->text = comm; return obj; } @@ -701,12 +731,12 @@ // If we cannot open the file, mark it an error if (!load) { - LDErrorObject* obj = new LDErrorObject (line, fmt ("Could not open %1", tokens[14])); + LDError* obj = new LDError (line, fmt ("Could not open %1", tokens[14])); obj->setFileRef (tokens[14]); return obj; } - LDSubfileObject* obj = new LDSubfileObject; + LDSubfile* obj = new LDSubfile; obj->setColor (tokens[1].toLong()); obj->setPosition (parseVertex (tokens, 2)); // 2 - 4 @@ -725,7 +755,7 @@ CHECK_TOKEN_NUMBERS (1, 7) // Line - LDLineObject* obj = new LDLineObject; + LDLine* obj = new LDLine; obj->setColor (tokens[1].toLong()); for (short i = 0; i < 2; ++i) @@ -739,7 +769,7 @@ CHECK_TOKEN_NUMBERS (1, 10) // Triangle - LDTriangleObject* obj = new LDTriangleObject; + LDTriangle* obj = new LDTriangle; obj->setColor (tokens[1].toLong()); for (short i = 0; i < 3; ++i) @@ -757,9 +787,9 @@ LDObject* obj; if (num == 4) - obj = new LDQuadObject; + obj = new LDQuad; else - obj = new LDCondLineObject; + obj = new LDCndLine; obj->setColor (tokens[1].toLong()); @@ -770,13 +800,12 @@ } default: // Strange line we couldn't parse - return new LDErrorObject (line, "Unknown line code number"); + return new LDError (line, "Unknown line code number"); } } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- LDFile* getFile (str filename) { // Try find the file in the list of loaded files LDFile* load = findLoadedFile (filename); @@ -789,8 +818,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void reloadAllSubfiles() { if (!LDFile::current()) return; @@ -799,21 +827,21 @@ g_loadedFiles << LDFile::current(); // Go through all objects in the current file and reload the subfiles - for (LDObject* obj : LDFile::current()->objs()) { + for (LDObject* obj : LDFile::current()->objects()) { if (obj->getType() == LDObject::Subfile) { - LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); + LDSubfile* ref = static_cast<LDSubfile*> (obj); LDFile* fileInfo = getFile (ref->fileInfo()->name()); if (fileInfo) ref->setFileInfo (fileInfo); else - ref->replace (new LDErrorObject (ref->raw(), "Could not open referred file")); + ref->replace (new LDError (ref->raw(), "Could not open referred file")); } // Reparse gibberish files. It could be that they are invalid because // of loading errors. Circumstances may be different now. if (obj->getType() == LDObject::Error) - obj->replace (parseLine (static_cast<LDErrorObject*> (obj)->contents)); + obj->replace (parseLine (static_cast<LDError*> (obj)->contents)); } // Close all files left unused @@ -821,11 +849,10 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- ulong LDFile::addObject (LDObject* obj) { - m_history.add (new AddHistory (m_objs.size(), obj)); - m_objs << obj; + m_history.add (new AddHistory (objects().size(), obj)); + m_objects << obj; if (obj->getType() == LDObject::Vertex) m_vertices << obj; @@ -835,25 +862,32 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ----------------------------------------------------------------------------- +void LDFile::addObjects (const List<LDObject*> objs) { + for (LDObject* obj : objs) + if (obj) + addObject (obj); +} + // ============================================================================= +// ----------------------------------------------------------------------------- void LDFile::insertObj (const ulong pos, LDObject* obj) { m_history.add (new AddHistory (pos, obj)); - m_objs.insert (pos, obj); + m_objects.insert (pos, obj); obj->setFile (this); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDFile::forgetObject (LDObject* obj) { ulong idx = obj->getIndex(); m_history.add (new DelHistory (idx, obj)); - m_objs.erase (idx); + m_objects.erase (idx); obj->setFile (null); } // ============================================================================= +// ----------------------------------------------------------------------------- bool safeToCloseAll() { for (LDFile* f : g_loadedFiles) if (!f->safeToClose()) @@ -863,6 +897,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void LDFile::setObject (ulong idx, LDObject* obj) { assert (idx < numObjs()); @@ -872,17 +907,19 @@ m_history << new EditHistory (idx, oldcode, newcode); obj->setFile (this); - m_objs[idx] = obj; + m_objects[idx] = obj; } +// ============================================================================= +// ----------------------------------------------------------------------------- static List<LDFile*> getFilesUsed (LDFile* node) { List<LDFile*> filesUsed; - for (LDObject* obj : *node) { + for (LDObject* obj : node->objects()) { if (obj->getType() != LDObject::Subfile) continue; - LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); + LDSubfile* ref = static_cast<LDSubfile*> (obj); filesUsed << ref->fileInfo(); filesUsed << getFilesUsed (ref->fileInfo()); } @@ -892,6 +929,7 @@ // ============================================================================= // Find out which files are unused and close them. +// ----------------------------------------------------------------------------- void LDFile::closeUnused() { List<LDFile*> filesUsed = getFilesUsed (LDFile::current()); @@ -922,32 +960,35 @@ g_loadedFiles << filesUsed; } +// ============================================================================= +// ----------------------------------------------------------------------------- LDObject* LDFile::object (ulong pos) const { - if (m_objs.size() <= pos) + if (m_objects.size() <= pos) return null; - return m_objs[pos]; + return m_objects[pos]; } +// ============================================================================= +// ----------------------------------------------------------------------------- LDObject* LDFile::obj (ulong pos) const { return object (pos); } +// ============================================================================= +// ----------------------------------------------------------------------------- ulong LDFile::numObjs() const { - return m_objs.size(); + return objects().size(); } -LDFile& LDFile::operator<< (List<LDObject*> objs) { - for (LDObject* obj : objs) - addObject (obj); - - return *this; -} - +// ============================================================================= +// ----------------------------------------------------------------------------- bool LDFile::hasUnsavedChanges() const { return !implicit() && history().pos() != savePos(); } +// ============================================================================= +// ----------------------------------------------------------------------------- str LDFile::getShortName() { if (name().length() > 0) return basename (name()); @@ -956,19 +997,83 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- +List<LDObject*> LDFile::inlineContents (LDSubfile::InlineFlags flags) { + // Possibly substitute with logoed studs: + // stud.dat -> stud-logo.dat + // stud2.dat -> stud-logo2.dat + if (gl_logostuds && (flags & LDSubfile::RendererInline)) { + if (name() == "stud.dat" && g_logoedStud) + return g_logoedStud->inlineContents (flags); + elif (name() == "stud2.dat" && g_logoedStud2) + return g_logoedStud2->inlineContents (flags); + } + + List<LDObject*> objs, objcache; + + bool deep = flags & LDSubfile::DeepInline, + doCache = flags & LDSubfile::CacheInline; + + // If we have this cached, just clone that + if (deep && cache().size()) { + for (LDObject* obj : cache()) + objs << obj->clone(); + } else { + if (!deep) + doCache = false; + + for (LDObject* obj : objects()) { + // Skip those without scemantic meaning + if (!obj->isScemantic()) + continue; + + // Got another sub-file reference, inline it if we're deep-inlining. If not, + // just add it into the objects normally. Also, we only cache immediate + // subfiles and this is not one. Yay, recursion! + if (deep && obj->getType() == LDObject::Subfile) { + LDSubfile* ref = static_cast<LDSubfile*> (obj); + + // We only want to cache immediate subfiles, so shed the caching + // flag when recursing deeper in hierarchy. + List<LDObject*> otherobjs = ref->inlineContents (flags & ~(LDSubfile::CacheInline)); + + for (LDObject* otherobj : otherobjs) { + // Cache this object, if desired + if (doCache) + objcache << otherobj->clone(); + + objs << otherobj; + } + } else { + if (doCache) + objcache << obj->clone(); + + objs << obj->clone(); + } + } + + if (doCache) + setCache (objcache); + } + + return objs; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- LDFile* LDFile::current() { return m_curfile; } // ============================================================================= -/* Sets the given file as the current one on display. At some point in time this - * was an operation completely unheard of. ;) - * - * FIXME: f can be temporarily null. This probably should not be the case. - */ +// Sets the given file as the current one on display. At some point in time this +// was an operation completely unheard of. ;) +// +// FIXME: f can be temporarily null. This probably should not be the case. +// ----------------------------------------------------------------------------- void LDFile::setCurrent (LDFile* f) { - /* Implicit files were loaded for caching purposes and must never be set - * current. */ + // Implicit files were loaded for caching purposes and must never be set + // current. if (f && f->implicit()) return; @@ -989,6 +1094,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- int LDFile::countExplicitFiles() { int count = 0; @@ -1002,12 +1108,24 @@ // ============================================================================= // This little beauty closes the initial file that was open at first when opening // a new file over it. +// ----------------------------------------------------------------------------- void LDFile::closeInitialFile() { - if (countExplicitFiles() == 2 && + if ( + countExplicitFiles() == 2 && g_loadedFiles[0]->name() == "" && - !g_loadedFiles[0]->hasUnsavedChanges()) { + !g_loadedFiles[0]->hasUnsavedChanges() + ) delete g_loadedFiles[0]; - } } -#include "build/moc_file.cpp" \ No newline at end of file +// ============================================================================= +// ----------------------------------------------------------------------------- +void loadLogoedStuds() { + print ("Loading logoed studs...\n"); + + delete g_logoedStud; + delete g_logoedStud2; + + g_logoedStud = openDATFile ("stud-logo.dat", true); + g_logoedStud2 = openDATFile ("stud2-logo.dat", true); +} \ No newline at end of file
--- a/src/file.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/file.h Sat Sep 07 13:23:09 2013 +0300 @@ -50,7 +50,7 @@ // ============================================================================= class LDFile : public QObject { Q_OBJECT - READ_PROPERTY (List<LDObject*>, objs, setObjects) + READ_PROPERTY (List<LDObject*>, objects, setObjects) READ_PROPERTY (History, history, setHistory) READ_PROPERTY (List<LDObject*>, vertices, setVertices) PROPERTY (str, name, setName) @@ -67,8 +67,11 @@ ~LDFile(); ulong addObject (LDObject* obj); // Adds an object to this file at the end of the file. + void addObjects (const List<LDObject*> objs); void forgetObject (LDObject* obj); // Deletes the given object from the object chain. + str getShortName(); bool hasUnsavedChanges() const; // Does this file have unsaved changes? + List<LDObject*> inlineContents (LDSubfile::InlineFlags flags); void insertObj (const ulong pos, LDObject* obj); ulong numObjs() const; LDObject* object (ulong pos) const; @@ -77,59 +80,19 @@ bool safeToClose(); // Perform safety checks. Do this before closing any files! void setObject (ulong idx, LDObject* obj); - LDFile& operator<< (LDObject* obj) { - addObject (obj); - return *this; - } - - LDFile& operator<< (List<LDObject*> objs); - - it begin() { - return PROP_NAME (objs).begin(); - } - - c_it begin() const { - return PROP_NAME (objs).begin(); - } - - it end() { - return PROP_NAME (objs).end(); - } - - c_it end() const { - return PROP_NAME (objs).end(); - } - - void openHistory() { - m_history.open(); - } - - void closeHistory() { - m_history.close(); - } - - void undo() { - m_history.undo(); - } - - void redo() { - m_history.redo(); - } - - void clearHistory() { - m_history.clear(); - } - - void addToHistory (AbstractHistoryEntry* entry) { - m_history << entry; - } + inline LDFile& operator<< (LDObject* obj) { addObject (obj); return *this; } + inline void openHistory() { m_history.open(); } + inline void closeHistory() { m_history.close(); } + inline void undo() { m_history.undo(); } + inline void redo() { m_history.redo(); } + inline void clearHistory() { m_history.clear(); } + inline void addToHistory (AbstractHistoryEntry* entry) { m_history << entry; } static void closeUnused(); static LDFile* current(); static void setCurrent (LDFile* f); static void closeInitialFile(); static int countExplicitFiles(); - str getShortName(); private: static LDFile* m_curfile; @@ -171,6 +134,7 @@ extern List<LDFile*> g_loadedFiles; void addRecentFile (str path); +void loadLogoedStuds(); str basename (str path); str dirname (str path);
--- a/src/gldata.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/gldata.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -5,7 +5,8 @@ #include "misc.h" #include "gldraw.h" -cfg (bool, gl_blackedges, true); +cfg (Bool, gl_blackedges, false); +static List<short> g_warnedColors; // ============================================================================= // ----------------------------------------------------------------------------- @@ -89,9 +90,7 @@ // ============================================================================= // ----------------------------------------------------------------------------- -void VertexCompiler::Array::merge ( - Array* other -) { +void VertexCompiler::Array::merge (Array* other) { // Ensure there's room for both buffers resizeToFit (writtenSize() + other->writtenSize()); @@ -101,94 +100,69 @@ // ============================================================================= // ----------------------------------------------------------------------------- -VertexCompiler::VertexCompiler() : m_file (null) { - for (int i = 0; i < NumArrays; ++i) { - m_mainArrays[i] = new Array; - m_changed[i] = false; - } -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -VertexCompiler::~VertexCompiler() { - for (Array* array : m_mainArrays) - delete array; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::compileVertex (::vertex v, QColor col, Array* array) { - VertexCompiler::Vertex glvertex; - glvertex.x = v.x(); - glvertex.y = -v.y(); - glvertex.z = v.z(); - glvertex.color = - (col.red() & 0xFF) << 0x00 | - (col.green() & 0xFF) << 0x08 | - (col.blue() & 0xFF) << 0x10 | - (col.alpha() & 0xFF) << 0x18; - - array->write (glvertex); +VertexCompiler::VertexCompiler() : + m_file (null) +{ + memset (m_changed, 0xFF, sizeof m_changed); } +VertexCompiler::~VertexCompiler() {} + // ============================================================================= +// Note: we use the top level object's color but the draw object's vertices. +// This is so that the index color is generated correctly - it has to reference +// the top level object's ID. This is crucial for picking to work. // ----------------------------------------------------------------------------- -// Note: we use the true object's color but the draw object's vertices. This is -// so that the index color is generated correctly - it has to reference the true -// object's ID. This is crucial for picking to work. void VertexCompiler::compilePolygon (LDObject* drawobj, LDObject* trueobj) { - Array** arrays = m_objArrays[trueobj]; - LDObject::Type objtype = drawobj->getType(); - const bool isline = (objtype == LDObject::Line || objtype == LDObject::CondLine); - const int verts = isline ? 2 : drawobj->vertices(); + List<CompiledTriangle>& data = m_objArrays[trueobj]; QColor normalColor = getObjectColor (trueobj, Normal), - pickColor = getObjectColor (trueobj, PickColor); + pickColor = getObjectColor (trueobj, PickColor); + + LDObject::Type type = drawobj->getType(); + assert (type != LDObject::Subfile); - for (int i = 0; i < verts; ++i) { - compileVertex (drawobj->getVertex (i), normalColor, arrays[isline ? EdgeArray : MainArray]); - compileVertex (drawobj->getVertex (i), pickColor, arrays[isline ? EdgePickArray : PickArray]); - } + List<LDObject*> objs; + if (type == LDObject::Quad) { + for (LDTriangle* t : static_cast<LDQuad*> (drawobj)->splitToTriangles()) + objs << t; + } else + objs << drawobj; - // For non-lines, compile BFC data. Note that the front objects are what get - // reversed here! This is because we invert the Y axis, which inverts the - // entire part model, so we remedy that here. - if (!isline) { - QColor col = getObjectColor (trueobj, BFCBack); - for (int i = 0; i < verts; ++i) - compileVertex (drawobj->getVertex(i), col, arrays[BFCArray]); + for (LDObject* obj : objs) { + const LDObject::Type objtype = obj->getType(); + const bool isline = (objtype == LDObject::Line || objtype == LDObject::CndLine); + const int verts = isline ? 2 : obj->vertices(); - col = getObjectColor (trueobj, BFCFront); - for (int i = verts - 1; i >= 0; --i) - compileVertex (drawobj->getVertex(i), col, arrays[BFCArray]); + CompiledTriangle a; + a.rgb = normalColor.rgb(); + a.pickrgb = pickColor.rgb(); + a.numVerts = verts; + a.obj = trueobj; + + for (int i = 0; i < verts; ++i) { + a.verts[i] = obj->getVertex (i); + a.verts[i].y() = -a.verts[i].y(); + } + + data << a; } } // ============================================================================= // ----------------------------------------------------------------------------- void VertexCompiler::compileObject (LDObject* obj, LDObject* topobj) { - if (m_objArrays.find (obj) == m_objArrays.end()) { - m_objArrays[obj] = new Array*[NumArrays]; - - for (int i = 0; i < NumArrays; ++i) - m_objArrays[obj][i] = new Array; - } else { - for (int i = 0; i < NumArrays; ++i) - m_objArrays[obj][i]->clear(); - } - + print ("compile %1 (%2)\n", obj->id(), topobj->id()); List<LDObject*> objs; switch (obj->getType()) { case LDObject::Triangle: compilePolygon (obj, topobj); - m_changed[MainArray] = true; break; case LDObject::Quad: - for (LDTriangleObject* triangle : static_cast<LDQuadObject*> (obj)->splitToTriangles()) + for (LDTriangle* triangle : static_cast<LDQuad*> (obj)->splitToTriangles()) compilePolygon (triangle, topobj); - m_changed[MainArray] = true; break; case LDObject::Line: @@ -196,7 +170,7 @@ break; case LDObject::Subfile: - objs = static_cast<LDSubfileObject*> (obj)->inlineContents (true, true); + objs = static_cast<LDSubfile*> (obj)->inlineContents (LDSubfile::RendererInline | LDSubfile::DeepCacheInline); for (LDObject* obj : objs) { compileObject (obj, topobj); @@ -207,22 +181,21 @@ default: break; } + + // Set all of m_changed to true + memset (m_changed, 0xFF, sizeof m_changed); } // ============================================================================= // ----------------------------------------------------------------------------- void VertexCompiler::compileFile() { - for (LDObject* obj : *m_file) + for (LDObject* obj : m_file->objects()) compileObject (obj, obj); } // ============================================================================= // ----------------------------------------------------------------------------- void VertexCompiler::forgetObject (LDObject* obj) { - for (int i = 0; i < NumArrays; ++i) - delete m_objArrays[obj][i]; - - delete m_objArrays[obj]; m_objArrays.remove (obj); } @@ -234,27 +207,111 @@ // ============================================================================= // ----------------------------------------------------------------------------- -VertexCompiler::Array* VertexCompiler::getMergedBuffer (ArrayType type) { +const VertexCompiler::Array* VertexCompiler::getMergedBuffer (ArrayType type) { assert (type < NumArrays); - if (m_changed) { + if (m_changed[type]) { m_changed[type] = false; - m_mainArrays[type]->clear(); + m_mainArrays[type].clear(); + + print ("merge array %1\n", (int) type); - for (LDObject* obj : *m_file) { + for (LDObject* obj : m_file->objects()) { + if (!obj->isScemantic()) + continue; + + const LDObject::Type objtype = obj->getType(); + const bool isline = (objtype == LDObject::Line || objtype == LDObject::CndLine); + const bool islinearray = (type == EdgeArray || type == EdgePickArray); + + if ((isline && !islinearray) || (!isline && islinearray)) + continue; + auto it = m_objArrays.find (obj); - if (it != m_objArrays.end()) - m_mainArrays[type]->merge ((*it)[type]); + if (it != m_objArrays.end()) { + const List<CompiledTriangle>& data = *it; + + for (const CompiledTriangle& i : data) { + Array* verts = postprocess (i, type); + m_mainArrays[type].merge (verts); + delete verts; + } + } } + + print ("merged array: %1 bytes\n", m_mainArrays[type].writtenSize()); } - return m_mainArrays[type]; + return &m_mainArrays[type]; +} + +// ============================================================================= +// This turns a compiled triangle into usable VAO vertices +// ----------------------------------------------------------------------------- +VertexCompiler::Array* VertexCompiler::postprocess (const CompiledTriangle& triangle, ArrayType type) { + Array* va = new Array; + List<Vertex> verts; + + for (int i = 0; i < triangle.numVerts; ++i) { + alias v0 = triangle.verts[i]; + Vertex v; + v.x = v0.x(); + v.y = v0.y(); + v.z = v0.z(); + + switch (type) { + case MainArray: + case EdgeArray: + v.color = triangle.rgb; + break; + + case PickArray: + case EdgePickArray: + v.color = triangle.pickrgb; + + case BFCArray: + break; + + case NumArrays: + assert (false); + } + + verts << v; + } + + if (type == BFCArray) { + int32 rgb = getObjectColor (triangle.obj, BFCFront).rgb(); + for (Vertex v : verts) { + v.color = rgb; + va->write (v); + } + + rgb = getObjectColor (triangle.obj, BFCBack).rgb(); + for (Vertex v : c_rev<Vertex> (verts)) { + v.color = rgb; + va->write (v); + } + } else { + for (Vertex v : verts) + va->write (v); + } + + return va; } // ============================================================================= // ----------------------------------------------------------------------------- -static List<short> g_warnedColors; +uint32 VertexCompiler::getColorRGB (QColor& color) { + return + (color.red() & 0xFF) << 0x00 | + (color.green() & 0xFF) << 0x08 | + (color.blue() & 0xFF) << 0x10 | + (color.alpha() & 0xFF) << 0x18; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- QColor VertexCompiler::getObjectColor (LDObject* obj, ColorType colotype) const { QColor qcol; @@ -280,7 +337,7 @@ if ((colotype == BFCFront || colotype == BFCBack) && obj->getType() != LDObject::Line && - obj->getType() != LDObject::CondLine) { + obj->getType() != LDObject::CndLine) { if (colotype == BFCFront) qcol = QColor (40, 192, 0);
--- a/src/gldata.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/gldata.h Sat Sep 07 13:23:09 2013 +0300 @@ -3,8 +3,10 @@ #include "types.h" #include <QMap> +#include <QRgb> class QColor; +class LDTriangle; class LDFile; /* ============================================================================= @@ -52,6 +54,14 @@ NumArrays }; + struct CompiledTriangle { + vertex verts[3]; + uint8 numVerts; + QRgb rgb; + QRgb pickrgb; + LDObject* obj; + }; + struct Vertex { float x, y, z; uint32 color; @@ -87,16 +97,18 @@ void compileFile(); void compileObject (LDObject* obj, LDObject* topobj); void forgetObject (LDObject* obj); - Array* getMergedBuffer (ArrayType type); + const Array* getMergedBuffer (ArrayType type); QColor getObjectColor (LDObject* obj, ColorType list) const; + static uint32 getColorRGB (QColor& color); + private: void compilePolygon (LDObject* drawobj, LDObject* trueobj); - void compileVertex (vertex v, QColor col, VertexCompiler::Array* array); + Array* postprocess (const CompiledTriangle& i, ArrayType type); - QMap<LDObject*, Array**> m_objArrays; + QMap<LDObject*, List<CompiledTriangle>> m_objArrays; QMap<LDFile*, Array*> m_fileCache; - Array* m_mainArrays[NumArrays]; + Array m_mainArrays[NumArrays]; LDFile* m_file; bool m_changed[NumArrays]; };
--- a/src/gldraw.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/gldraw.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -51,14 +51,15 @@ {{ 0, -1, 0 }, Z, Y, false, true }, }; -cfg (str, gl_bgcolor, "#CCCCD9"); -cfg (str, gl_maincolor, "#707078"); -cfg (float, gl_maincolor_alpha, 1.0); -cfg (int, gl_linethickness, 2); -cfg (bool, gl_colorbfc, true); -cfg (int, gl_camera, GLRenderer::Free); -cfg (bool, gl_axes, false); -cfg (bool, gl_wireframe, false); +cfg (String, gl_bgcolor, "#CCCCD9"); +cfg (String, gl_maincolor, "#707078"); +cfg (Float, gl_maincolor_alpha, 1.0); +cfg (Int, gl_linethickness, 2); +cfg (Bool, gl_colorbfc, false); +cfg (Int, gl_camera, GLRenderer::Free); +cfg (Bool, gl_axes, false); +cfg (Bool, gl_wireframe, false); +cfg (Bool, gl_logostuds, false); // argh const char* g_CameraNames[7] = { @@ -90,12 +91,16 @@ { QColor (0, 160, 192), vertex (0, 0, 10000) }, }; -#warning this should be a member -static VertexCompiler g_vertexCompiler; // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +#warning this should be a member +static VertexCompiler g_vertexCompiler; +static bool g_glInvert = false; +static List<short> g_warnedColors; + // ============================================================================= +// ----------------------------------------------------------------------------- GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent) { m_picking = m_rangepick = false; m_camera = (GL::Camera) gl_camera.value; @@ -134,6 +139,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- GLRenderer::~GLRenderer() { for (int i = 0; i < 6; ++i) delete m_overlays[i].img; @@ -143,8 +149,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::calcCameraIcons() { ushort i = 0; @@ -160,6 +165,8 @@ } } +// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::initGLData() { glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -175,6 +182,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::resetAngles() { m_rotX = 30.0f; m_rotY = 325.f; @@ -183,8 +191,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::initializeGL() { setBackground(); @@ -198,8 +205,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- QColor GLRenderer::getMainColor() { QColor col (gl_maincolor); @@ -210,6 +216,7 @@ return col; } +// ============================================================================= // ----------------------------------------------------------------------------- void GLRenderer::setBackground() { QColor col (gl_bgcolor); @@ -225,14 +232,14 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::refresh() { update(); swapBuffers(); } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::hardRefresh() { g_vertexCompiler.compileFile(); refresh(); @@ -241,8 +248,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::resizeGL (int w, int h) { m_width = w; m_height = h; @@ -256,6 +262,8 @@ glMatrixMode (GL_MODELVIEW); } +// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::drawGLScene() { if (file() == null) return; @@ -266,7 +274,7 @@ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable (GL_DEPTH_TEST); - if (m_camera != GLRenderer::Free) { + if (m_camera != Free) { glMatrixMode (GL_PROJECTION); glPushMatrix(); @@ -274,9 +282,11 @@ glOrtho (-m_virtWidth, m_virtWidth, -m_virtHeight, m_virtHeight, -100.0f, 100.0f); glTranslatef (m_panX, m_panY, 0.0f); - glRotatef (90.0f, g_staticCameras[m_camera].glrotate[0], - g_staticCameras[m_camera].glrotate[1], - g_staticCameras[m_camera].glrotate[2]); + if (m_camera != Front && m_camera != Back) { + glRotatef (90.0f, g_staticCameras[m_camera].glrotate[0], + g_staticCameras[m_camera].glrotate[1], + g_staticCameras[m_camera].glrotate[2]); + } // Back camera needs to be handled differently if (m_camera == GL::Back) { @@ -306,7 +316,7 @@ } else glDisable (GL_CULL_FACE); - VertexCompiler::Array* array = g_vertexCompiler.getMergedBuffer ( + const VertexCompiler::Array* array = g_vertexCompiler.getMergedBuffer ( (m_picking) ? VertexCompiler::PickArray : (gl_colorbfc) ? VertexCompiler::BFCArray : VertexCompiler::MainArray); @@ -328,9 +338,10 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- // This converts a 2D point on the screen to a 3D point in the model. If 'snap' // is true, the 3D point will snap to the current grid. -// ============================================================================= +// ----------------------------------------------------------------------------- vertex GLRenderer::coordconv2_3 (const QPoint& pos2d, bool snap) const { assert (camera() != Free); @@ -362,9 +373,10 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- // Inverse operation for the above - convert a 3D position to a 2D screen // position -// ============================================================================= +// ----------------------------------------------------------------------------- QPoint GLRenderer::coordconv3_2 (const vertex& pos3d) const { GLfloat m[16]; const staticCameraMeta* cam = &g_staticCameras[m_camera]; @@ -391,8 +403,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::paintEvent (QPaintEvent* ev) { Q_UNUSED (ev) @@ -429,7 +440,7 @@ QFontMetrics metrics = QFontMetrics (font()); QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text); - paint.setPen (m_darkbg ? Qt::white : Qt::black); + paint.setPen (getTextPen()); paint.drawText (m_width - textSize.width(), m_height - 16, textSize.width(), textSize.height(), Qt::AlignCenter, text); @@ -517,13 +528,13 @@ str fmtstr = tr ("%1 Camera"); - // Draw a label for the current camera in the top left corner + // Draw a label for the current camera in the bottom left corner { const ushort margin = 4; str label; label = fmt (fmtstr, tr (g_CameraNames[camera()])); - paint.setPen (m_darkbg ? Qt::white : Qt::black); + paint.setPen (getTextPen()); paint.drawText (QPoint (margin, height() - (margin + metrics.descent())), label); } @@ -542,12 +553,11 @@ if (msglog()) { int y = 0; const int margin = 2; - QColor col = Qt::black; - paint.setPen (QPen()); + QColor penColor = getTextPen(); - for (const MessageManager::Line& line : *msglog()) { - col.setAlphaF (line.alpha); - paint.setPen (QPen (col)); + for (const MessageManager::Line& line : msglog()->getLines()) { + penColor.setAlphaF (line.alpha); + paint.setPen (penColor); paint.drawText (QPoint (margin, y + margin + metrics.ascent()), line.text); y += metrics.height(); } @@ -571,15 +581,19 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ----------------------------------------------------------------------------- +QColor GLRenderer::getTextPen () const { + return m_darkbg ? Qt::white : Qt::black; +} + // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::compileAllObjects() { g_vertexCompiler.compileFile(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::clampAngle (double& angle) const { while (angle < 0) angle += 360.0; @@ -587,6 +601,8 @@ angle -= 360.0; } +// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::addDrawnVertex (vertex pos) { // If we picked an already-existing vertex, stop drawing for (vertex& vert : m_drawedVerts) { @@ -600,8 +616,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::mouseReleaseEvent (QMouseEvent* ev) { const bool wasLeft = (m_lastButtons & Qt::LeftButton) && !(ev->buttons() & Qt::LeftButton), wasRight = (m_lastButtons & Qt::RightButton) && !(ev->buttons() & Qt::RightButton), @@ -710,8 +725,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::mousePressEvent (QMouseEvent* ev) { m_totalmove = 0; @@ -768,17 +782,19 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::keyPressEvent (QKeyEvent* ev) { m_keymods = ev->modifiers(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::keyReleaseEvent (QKeyEvent* ev) { m_keymods = ev->modifiers(); } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::wheelEvent (QWheelEvent* ev) { makeCurrent(); @@ -790,6 +806,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::leaveEvent (QEvent* ev) { (void) ev; m_drawToolTip = false; @@ -798,11 +815,13 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::contextMenuEvent (QContextMenuEvent* ev) { g_win->spawnContextMenu (ev->globalPos()); } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::setCamera (const GL::Camera cam) { m_camera = cam; gl_camera = (int) cam; @@ -810,8 +829,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::pick (uint mouseX, uint mouseY) { GLint viewport[4]; makeCurrent(); @@ -944,10 +962,13 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- READ_ACCESSOR (EditMode, GLRenderer::editMode) { return m_editMode; } +// ============================================================================= +// ----------------------------------------------------------------------------- SET_ACCESSOR (EditMode, GLRenderer::setEditMode) { m_editMode = val; @@ -982,10 +1003,14 @@ update(); } +// ============================================================================= +// ----------------------------------------------------------------------------- READ_ACCESSOR (LDFile*, GLRenderer::file) { return m_file; } +// ============================================================================= +// ----------------------------------------------------------------------------- SET_ACCESSOR (LDFile*, GLRenderer::setFile) { m_file = val; g_vertexCompiler.setFile (val); @@ -995,6 +1020,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::endDraw (bool accept) { (void) accept; @@ -1003,7 +1029,7 @@ LDObject* obj = null; if (m_rectdraw) { - LDQuadObject* quad = new LDQuadObject; + LDQuad* quad = new LDQuad; // Copy the vertices from m_rectverts updateRectVerts(); @@ -1017,22 +1043,22 @@ switch (verts.size()) { case 1: // 1 vertex - add a vertex object - obj = new LDVertexObject; - static_cast<LDVertexObject*> (obj)->pos = verts[0]; + obj = new LDVertex; + static_cast<LDVertex*> (obj)->pos = verts[0]; obj->setColor (maincolor); break; case 2: // 2 verts - make a line - obj = new LDLineObject (verts[0], verts[1]); + obj = new LDLine (verts[0], verts[1]); obj->setColor (edgecolor); break; case 3: case 4: obj = (verts.size() == 3) ? - static_cast<LDObject*> (new LDTriangleObject) : - static_cast<LDObject*> (new LDQuadObject); + static_cast<LDObject*> (new LDTriangle) : + static_cast<LDObject*> (new LDQuad); obj->setColor (maincolor); for (ushort i = 0; i < obj->vertices(); ++i) @@ -1053,6 +1079,8 @@ m_rectdraw = false; } +// ============================================================================= +// ----------------------------------------------------------------------------- static List<vertex> getVertices (LDObject* obj) { List<vertex> verts; @@ -1060,7 +1088,8 @@ for (int i = 0; i < obj->vertices(); ++i) verts << obj->getVertex (i); } elif (obj->getType() == LDObject::Subfile) { - List<LDObject*> objs = static_cast<LDSubfileObject*> (obj)->inlineContents (true, true); + LDSubfile* ref = static_cast<LDSubfile*> (obj); + List<LDObject*> objs = ref->inlineContents (LDSubfile::DeepCacheInline); for(LDObject* obj : objs) { verts << getVertices (obj); @@ -1072,14 +1101,14 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::compileObject (LDObject* obj) { g_vertexCompiler.compileObject (obj, obj); obj->m_glinit = true; } // ============================================================================= +// ----------------------------------------------------------------------------- uchar* GLRenderer::screencap (ushort& w, ushort& h) { w = m_width; h = m_height; @@ -1096,6 +1125,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::slot_toolTipTimer() { // We come here if the cursor has stayed in one place for longer than a // a second. Check if we're holding it over a camera icon - if so, draw @@ -1111,6 +1141,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::deleteLists (LDObject* obj) { // Delete the lists but only if they have been initialized if (!obj->m_glinit) @@ -1123,6 +1154,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- Axis GLRenderer::cameraAxis (bool y, GL::Camera camid) { if (camid == (GL::Camera) -1) camid = m_camera; @@ -1132,6 +1164,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- bool GLRenderer::setupOverlay (GL::Camera cam, str file, int x, int y, int w, int h) { QImage* img = new QImage (file); overlayMeta& info = getOverlay (cam); @@ -1158,27 +1191,29 @@ const Axis x2d = cameraAxis (false, cam), y2d = cameraAxis (true, cam); - + double negXFac = g_staticCameras[cam].negX ? -1 : 1, negYFac = g_staticCameras[cam].negY ? -1 : 1; - + info.v0 = info.v1 = g_origin; info.v0[x2d] = - (info.ox * info.lw * negXFac) / img->width(); info.v0[y2d] = (info.oy * info.lh * negYFac) / img->height(); info.v1[x2d] = info.v0[x2d] + info.lw; info.v1[y2d] = info.v0[y2d] + info.lh; - + // Set alpha of all pixels to 0.5 for (long i = 0; i < img->width(); ++i) for (long j = 0; j < img->height(); ++j) { uint32 pixel = img->pixel (i, j); img->setPixel (i, j, 0x80000000 | (pixel & 0x00FFFFFF)); } - + updateOverlayObjects(); return true; } +// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::clearOverlay() { if (camera() == Free) return; @@ -1190,24 +1225,34 @@ updateOverlayObjects(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::setDepthValue (double depth) { assert (camera() < Free); m_depthValues[camera()] = depth; } +// ============================================================================= +// ----------------------------------------------------------------------------- double GLRenderer::depthValue() const { assert (camera() < Free); return m_depthValues[camera()]; } +// ============================================================================= +// ----------------------------------------------------------------------------- const char* GLRenderer::cameraName() const { return g_CameraNames[camera()]; } +// ============================================================================= +// ----------------------------------------------------------------------------- overlayMeta& GLRenderer::getOverlay (int newcam) { return m_overlays[newcam]; } +// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::zoomNotch (bool inward) { if (zoom() > 15) setZoom (zoom() * (inward ? 0.833f : 1.2f)); @@ -1216,6 +1261,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::zoomToFit() { if (file() == null) { setZoom (30.0f); @@ -1294,6 +1340,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::updateRectVerts() { if (!m_rectdraw) return; @@ -1325,6 +1372,8 @@ m_rectverts[3][ay] = v1[ay]; } +// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::mouseDoubleClickEvent (QMouseEvent* ev) { if (!(ev->buttons() & Qt::LeftButton) || editMode() != Select) return; @@ -1341,12 +1390,14 @@ ev->accept(); } -LDOverlayObject* GLRenderer::findOverlayObject (GLRenderer::Camera cam) { - LDOverlayObject* ovlobj = null; +// ============================================================================= +// ----------------------------------------------------------------------------- +LDOverlay* GLRenderer::findOverlayObject (GLRenderer::Camera cam) { + LDOverlay* ovlobj = null; - for (LDObject * obj : *file()) { - if (obj->getType() == LDObject::Overlay && static_cast<LDOverlayObject*> (obj)->camera() == cam) { - ovlobj = static_cast<LDOverlayObject*> (obj); + for (LDObject * obj : file()->objects()) { + if (obj->getType() == LDObject::Overlay && static_cast<LDOverlay*> (obj)->camera() == cam) { + ovlobj = static_cast<LDOverlay*> (obj); break; } } @@ -1357,14 +1408,14 @@ // ============================================================================= // ----------------------------------------------------------------------------- // Read in overlays from the current file and update overlay info accordingly. -// ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::overlaysFromObjects() { for (Camera cam : g_Cameras) { if (cam == Free) continue; overlayMeta& meta = m_overlays[cam]; - LDOverlayObject* ovlobj = findOverlayObject (cam); + LDOverlay* ovlobj = findOverlayObject (cam); if (!ovlobj && meta.img) { delete meta.img; @@ -1375,13 +1426,14 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void GLRenderer::updateOverlayObjects() { for (Camera cam : g_Cameras) { if (cam == Free) continue; overlayMeta& meta = m_overlays[cam]; - LDOverlayObject* ovlobj = findOverlayObject (cam); + LDOverlay* ovlobj = findOverlayObject (cam); if (!meta.img && ovlobj) { // If this is the last overlay image, we need to remove the empty space after it as well. @@ -1399,7 +1451,7 @@ } elif (meta.img && !ovlobj) { // Inverse case: image is there but the overlay object is // not, thus create the object. - ovlobj = new LDOverlayObject; + ovlobj = new LDOverlay; // Find a suitable position to place this object. We want to place // this into the header, which is everything up to the first scemantic @@ -1428,7 +1480,7 @@ file()->insertObj (i, ovlobj); if (found) - file()->insertObj (i + 1, new LDEmptyObject); + file()->insertObj (i + 1, new LDEmpty); } }
--- a/src/gldraw.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/gldraw.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -25,7 +25,7 @@ class MessageManager; class QDialogButtonBox; -class RadioBox; +class RadioGroup; class QDoubleSpinBox; class QSpinBox; class QLineEdit; @@ -147,9 +147,10 @@ void clampAngle (double& angle) const; // Clamps an angle to [0, 360] vertex coordconv2_3 (const QPoint& pos2d, bool snap) const; // Convert a 2D point to a 3D point QPoint coordconv3_2 (const vertex& pos3d) const; // Convert a 3D point to a 2D point - LDOverlayObject* findOverlayObject (Camera cam); + LDOverlay* findOverlayObject (Camera cam); void updateRectVerts(); void pick (uint mouseX, uint mouseY); // Perform object selection + QColor getTextPen() const; // Determine which color to draw text with private slots: void slot_toolTipTimer();
--- a/src/gui.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/gui.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -51,17 +51,17 @@ static bool g_bSelectionLocked = false; -cfg (bool, lv_colorize, true); -cfg (str, gui_colortoolbar, "16:24:|:1:2:4:14:0:15:|:33:34:36:46"); -cfg (bool, gui_implicitfiles, false); -extern_cfg (str, io_recentfiles); -extern_cfg (bool, gl_axes); -extern_cfg (str, gl_maincolor); -extern_cfg (float, gl_maincolor_alpha); -extern_cfg (bool, gl_wireframe); -extern_cfg (bool, gl_colorbfc); +cfg (Bool, lv_colorize, true); +cfg (String, gui_colortoolbar, "16:24:|:1:2:4:14:0:15:|:33:34:36:46"); +cfg (Bool, gui_implicitfiles, false); +extern_cfg (List, io_recentfiles); +extern_cfg (Bool, gl_axes); +extern_cfg (String, gl_maincolor); +extern_cfg (Float, gl_maincolor_alpha); +extern_cfg (Bool, gl_wireframe); +extern_cfg (Bool, gl_colorbfc); -#define act(N) extern_cfg (keyseq, key_##N); +#define act(N) extern_cfg (KeySequence, key_##N); #include "actions.h" const char* g_modeActionNames[] = { @@ -70,8 +70,7 @@ }; // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- ForgeWindow::ForgeWindow() { g_win = this; m_renderer = new GLRenderer; @@ -125,12 +124,16 @@ #include "actions.h" } +// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::slot_action() { // Find out which action triggered this #define act(N) if (sender() == ui->action##N) invokeAction (ui->action##N, &actiondef_##N); #include "actions.h" } +// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::invokeAction (QAction* act, void (*func)()) { beginAction (act); (*func)(); @@ -138,47 +141,46 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::slot_lastSecondCleanup() { delete m_renderer; delete ui; } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::updateRecentFilesMenu() { - QStringList files = io_recentfiles.value.split ("@", QString::SkipEmptyParts); - QStringListIterator it (files); - // First, clear any items in the recent files menu for (QAction* recent : m_recentFiles) delete recent; m_recentFiles.clear(); - it.toBack(); - while (it.hasPrevious()) { - str file = it.previous(); + QAction* first = null; + + for (const QVariant& it : io_recentfiles) { + str file = it.toString(); QAction* recent = new QAction (getIcon ("open-recent"), file, this); connect (recent, SIGNAL (triggered()), this, SLOT (slot_recentFile())); - ui->menuOpenRecent->addAction (recent); + ui->menuOpenRecent->insertAction (first, recent); m_recentFiles << recent; + first = recent; } } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- List<LDQuickColor> quickColorsFromConfig() { List<LDQuickColor> colors; for (str colorname : gui_colortoolbar.value.split (":")) { - if (colorname == "|") { - colors << LDQuickColor ({null, null, true}); - } else { + if (colorname == "|") + colors << LDQuickColor::getSeparator(); + else { LDColor* col = getColor (colorname.toLong()); - assert (col != null); - colors << LDQuickColor ({col, null, false}); + + if (col != null) + colors << LDQuickColor (col, null); } } @@ -186,26 +188,25 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::updateToolBars() { m_colorButtons.clear(); ui->colorToolbar->clear(); for (LDQuickColor& entry : m_quickColors) { - if (entry.isSeparator) + if (entry.isSeparator()) ui->colorToolbar->addSeparator(); else { QToolButton* colorButton = new QToolButton; - colorButton->setIcon (makeColorIcon (entry.col, 22)); + colorButton->setIcon (makeColorIcon (entry.color(), 22)); colorButton->setIconSize (QSize (22, 22)); - colorButton->setToolTip (entry.col->name); + colorButton->setToolTip (entry.color()->name); connect (colorButton, SIGNAL (clicked()), this, SLOT (slot_quickColor())); ui->colorToolbar->addWidget (colorButton); m_colorButtons << colorButton; - entry.btn = colorButton; + entry.setToolButton (colorButton); } } @@ -213,8 +214,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::updateGridToolBar() { // Ensure that the current grid - and only the current grid - is selected. ui->actionGridCoarse->setChecked (grid == Grid::Coarse); @@ -223,8 +223,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::updateTitle() { str title = fmt (APPNAME " %1", fullVersionString()); @@ -239,7 +238,7 @@ LDFile::current()->obj (0)->getType() == LDObject::Comment) { // Append title - LDCommentObject* comm = static_cast<LDCommentObject*> (LDFile::current()->obj (0)); + LDComment* comm = static_cast<LDComment*> (LDFile::current()->obj (0)); title += fmt (": %1", comm->text); } @@ -251,10 +250,8 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -int ForgeWindow::deleteSelection() -{ +// ----------------------------------------------------------------------------- +int ForgeWindow::deleteSelection() { if (m_sel.size() == 0) return 0; @@ -273,8 +270,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::buildObjList() { if (!LDFile::current()) return; @@ -289,12 +285,12 @@ ui->objectList->clear(); - for (LDObject* obj : LDFile::current()->objs()) { + for (LDObject* obj : LDFile::current()->objects()) { str descr; switch (obj->getType()) { case LDObject::Comment: - descr = static_cast<LDCommentObject*> (obj)->text; + descr = static_cast<LDComment*> (obj)->text; // Remove leading whitespace while (descr[0] == ' ') @@ -307,7 +303,7 @@ case LDObject::Line: case LDObject::Triangle: case LDObject::Quad: - case LDObject::CondLine: + case LDObject::CndLine: for (short i = 0; i < obj->vertices(); ++i) { if (i != 0) descr += ", "; @@ -321,12 +317,12 @@ break; case LDObject::Vertex: - descr = static_cast<LDVertexObject*> (obj)->pos.stringRep (true); + descr = static_cast<LDVertex*> (obj)->pos.stringRep (true); break; case LDObject::Subfile: { - LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); + LDSubfile* ref = static_cast<LDSubfile*> (obj); descr = fmt ("%1 %2, (", ref->fileInfo()->name(), ref->position().stringRep (true)); @@ -340,12 +336,12 @@ break; case LDObject::BFC: - descr = LDBFCObject::statements[static_cast<LDBFCObject*> (obj)->type]; - break; + descr = LDBFC::statements[static_cast<LDBFC*> (obj)->type]; + break; case LDObject::Overlay: { - LDOverlayObject* ovl = static_cast<LDOverlayObject*> (obj); + LDOverlay* ovl = static_cast<LDOverlay*> (obj); descr = fmt ("[%1] %2 (%3, %4), %5 x %6", g_CameraNames[ovl->camera()], basename (ovl->filename()), ovl->x(), ovl->y(), ovl->width(), ovl->height()); } @@ -357,9 +353,8 @@ } // Put it into brackets if it's hidden - if (obj->hidden()) { + if (obj->hidden()) descr = fmt ("[[ %1 ]]", descr); - } QListWidgetItem* item = new QListWidgetItem (descr); item->setIcon (getIcon (obj->typeName())); @@ -388,8 +383,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::scrollToSelection() { if (m_sel.size() == 0) return; @@ -399,8 +393,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::slot_selectionChanged() { if (g_bSelectionLocked == true || LDFile::current() == null) return; @@ -417,7 +410,7 @@ m_sel.clear(); const QList<QListWidgetItem*> items = ui->objectList->selectedItems(); - for (LDObject* obj : LDFile::current()->objs()) + for (LDObject* obj : LDFile::current()->objects()) for (QListWidgetItem* item : items) { if (item == obj->qObjListEntry) { m_sel << obj; @@ -440,22 +433,22 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::slot_recentFile() { QAction* qAct = static_cast<QAction*> (sender()); openMainFile (qAct->text()); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::slot_quickColor() { beginAction (null); QToolButton* button = static_cast<QToolButton*> (sender()); LDColor* col = null; - for (LDQuickColor entry : m_quickColors) { - if (entry.btn == button) { - col = entry.col; + for (const LDQuickColor& entry : m_quickColors) { + if (entry.toolButton() == button) { + col = entry.color(); break; } } @@ -478,8 +471,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- ulong ForgeWindow::getInsertionPoint() { if (m_sel.size() > 0) { // If we have a selection, put the item after it. @@ -491,25 +483,25 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::fullRefresh() { buildObjList(); m_renderer->hardRefresh(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::refresh() { buildObjList(); m_renderer->update(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::updateSelection() { g_bSelectionLocked = true; - for (LDObject* obj : LDFile::current()->objs()) + for (LDObject* obj : LDFile::current()->objects()) obj->setSelected (false); ui->objectList->clearSelection(); @@ -526,8 +518,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- bool ForgeWindow::isSelected (LDObject* obj) { LDObject* needle = obj->topLevelParent(); @@ -556,8 +547,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- LDObject::Type ForgeWindow::uniformSelectedType() { LDObject::Type result = LDObject::Unidentified; @@ -573,8 +563,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::closeEvent (QCloseEvent* ev) { // Check whether it's safe to close all files. if (!safeToCloseAll()) { @@ -584,14 +573,13 @@ // Save the configuration before leaving so that, for instance, grid choice // is preserved across instances. - config::save(); + Config::save(); ev->accept(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::spawnContextMenu (const QPoint pos) { const bool single = (g_win->sel().size() == 1); LDObject* singleObj = (single) ? g_win->sel()[0] : null; @@ -628,6 +616,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::deleteObjVector (List<LDObject*> objs) { for (LDObject* obj : objs) { LDFile::current()->forgetObject (obj); @@ -636,9 +625,10 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::deleteByColor (const short colnum) { List<LDObject*> objs; - for (LDObject* obj : LDFile::current()->objs()) { + for (LDObject* obj : LDFile::current()->objects()) { if (!obj->isColored() || obj->color() != colnum) continue; @@ -649,15 +639,18 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::updateEditModeActions() { const EditMode mode = R()->editMode(); ACTION (ModeSelect)->setChecked (mode == Select); ACTION (ModeDraw)->setChecked (mode == Draw); } +// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::slot_editObject (QListWidgetItem* listitem) { LDObject* obj = null; - for (LDObject* it : *LDFile::current()) { + for (LDObject* it : LDFile::current()->objects()) { if (it->qObjListEntry == listitem) { obj = it; break; @@ -667,6 +660,8 @@ AddObjectDialog::staticDialog (obj->getType(), obj); } +// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::primitiveLoaderStart (ulong max) { m_primLoaderWidget->show(); m_primLoaderBar->setRange (0, max); @@ -674,10 +669,14 @@ m_primLoaderBar->setFormat ("%p%"); } +// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::primitiveLoaderUpdate (ulong prog) { m_primLoaderBar->setValue (prog); } +// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::primitiveLoaderEnd() { QTimer* hidetimer = new QTimer; connect (hidetimer, SIGNAL (timeout()), m_primLoaderWidget, SLOT (hide())); @@ -688,8 +687,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void ForgeWindow::save (LDFile* f, bool saveAs) { str path = f->name(); @@ -742,8 +740,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- QPixmap getIcon (str iconName) { return (QPixmap (fmt (":/icons/%1.png", iconName))); } @@ -788,7 +785,7 @@ void makeColorSelector (QComboBox* box) { std::map<short, ulong> counts; - for (LDObject* obj : LDFile::current()->objs()) { + for (LDObject* obj : LDFile::current()->objects()) { if (!obj->isColored()) continue; @@ -832,12 +829,12 @@ ui->fileList->clear(); for (LDFile* f : g_loadedFiles) { - /* Don't list implicit files unless explicitly desired. */ + // Don't list implicit files unless explicitly desired. if (f->implicit() && !gui_implicitfiles) continue; - /* Add an item to the list for this file and store a pointer to it in - * the file, so we can find files by the list item. */ + // Add an item to the list for this file and store a pointer to it in + // the file, so we can find files by the list item. ui->fileList->addItem (""); QListWidgetItem* item = ui->fileList->item (ui->fileList->count() - 1); f->setListItem (item); @@ -848,25 +845,25 @@ void ForgeWindow::updateFileListItem (LDFile* f) { if (f->listItem() == null) { - /* We don't have a list item for this file, so the list either doesn't - * exist yet or is out of date. Build the list now. */ + // We don't have a list item for this file, so the list either doesn't + // exist yet or is out of date. Build the list now. updateFileList(); return; } - /* If this is the current file, it also needs to be the selected item on - * the list. */ + // If this is the current file, it also needs to be the selected item on + // the list. if (f == LDFile::current()) ui->fileList->setCurrentItem (f->listItem()); - /* If we list implicit files, draw them with a shade of gray to make them - * distinct. */ + // If we list implicit files, draw them with a shade of gray to make them + // distinct. if (f->implicit()) f->listItem()->setForeground (QColor (96, 96, 96)); f->listItem()->setText (f->getShortName()); - /* If the file has unsaved changes, draw a little icon next to it to mark that. */ + // If the file has unsaved changes, draw a little icon next to it to mark that. f->listItem()->setIcon (f->hasUnsavedChanges() ? getIcon ("file-save") : QIcon()); } @@ -880,20 +877,19 @@ // Close the history now. LDFile::current()->closeHistory(); - /* Update the list item of the current file - we may need to draw an icon - * now that marks it as having unsaved changes. */ + // Update the list item of the current file - we may need to draw an icon + // now that marks it as having unsaved changes. updateFileListItem (LDFile::current()); } // ============================================================================= -/* A file is selected from the list of files on the left of the screen. Find out - * which file was picked and change to it. - */ +// A file is selected from the list of files on the left of the screen. Find out +// which file was picked and change to it. void ForgeWindow::changeCurrentFile() { LDFile* f = null; QListWidgetItem* item = ui->fileList->currentItem(); - /* Find the file pointer of the item that was selected. */ + // Find the file pointer of the item that was selected. for (LDFile* it : g_loadedFiles) { if (it->listItem() == item) { f = it; @@ -901,8 +897,8 @@ } } - /* If we picked the same file we're currently on, we don't need to do - * anything. */ + // If we picked the same file we're currently on, we don't need to do + // anything. if (!f || f == LDFile::current()) return; @@ -926,4 +922,16 @@ return QImage (data, w, h, QImage::Format_ARGB32).rgbSwapped().mirrored(); } -#include "build/moc_gui.cpp" \ No newline at end of file +// ============================================================================= +// ----------------------------------------------------------------------------- +LDQuickColor::LDQuickColor (LDColor* color, QToolButton* toolButton) : + m_color (color), + m_toolButton (toolButton) {} + +LDQuickColor LDQuickColor::getSeparator() { + return LDQuickColor (null, null); +} + +bool LDQuickColor::isSeparator() const { + return color() == null; +} \ No newline at end of file
--- a/src/gui.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/gui.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -46,7 +46,7 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= #define DEFINE_ACTION(NAME, DEFSHORTCUT) \ - cfg (keyseq, key_##NAME, DEFSHORTCUT); \ + cfg (KeySequence, key_##NAME, DEFSHORTCUT); \ void actiondef_##NAME() #define ACTION(N) g_win->action##N() @@ -58,10 +58,15 @@ #define CTRL_SHIFT(N) (Qt::CTRL | Qt::SHIFT | Qt::Key_##N) // ============================================================================= -struct LDQuickColor { - LDColor* col; - QToolButton* btn; - bool isSeparator; +class LDQuickColor { + PROPERTY (LDColor*, color, setColor) + PROPERTY (QToolButton*, toolButton, setToolButton) + +public: + LDQuickColor (LDColor* color, QToolButton* toolButton); + bool isSeparator() const; + + static LDQuickColor getSeparator(); }; // =============================================================================
--- a/src/gui_actions.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/gui_actions.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -29,7 +29,6 @@ #include "history.h" #include "configDialog.h" #include "addObjectDialog.h" -#include "aboutDialog.h" #include "misc.h" #include "gldraw.h" #include "dialogs.h" @@ -37,56 +36,82 @@ #include "ui_newpart.h" #include "widgets.h" -extern_cfg (bool, gl_wireframe); -extern_cfg (bool, gl_colorbfc); +extern_cfg (Bool, gl_wireframe); +extern_cfg (Bool, gl_colorbfc); +extern_cfg (String, ld_defaultname); +extern_cfg (String, ld_defaultuser); +extern_cfg (Int, ld_defaultlicense); // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (New, CTRL_SHIFT (N)) { QDialog* dlg = new QDialog (g_win); Ui::NewPartUI ui; ui.setupUi (dlg); + str authortext = ld_defaultname; + + if (!ld_defaultuser.value.isEmpty()) + authortext.append (fmt (" [%1]", ld_defaultuser)); + + ui.le_author->setText (authortext); + + switch (ld_defaultlicense) { + case 0: + ui.rb_license_ca->setChecked (true); + break; + + case 1: + ui.rb_license_nonca->setChecked (true); + break; + + case 2: + ui.rb_license_none->setChecked (true); + break; + + default: + QMessageBox::warning (null, "Warning", + fmt ("Unknown ld_defaultlicense value %1!", ld_defaultlicense)); + break; + } + if (dlg->exec() == false) return; newFile(); - const LDBFCObject::Type BFCType = - ui.rb_bfc_ccw->isChecked() ? LDBFCObject::CertifyCCW : - ui.rb_bfc_cw->isChecked() ? LDBFCObject::CertifyCW : LDBFCObject::NoCertify; + const LDBFC::Type BFCType = + ui.rb_bfc_ccw->isChecked() ? LDBFC::CertifyCCW : + ui.rb_bfc_cw->isChecked() ? LDBFC::CertifyCW : LDBFC::NoCertify; const str license = ui.rb_license_ca->isChecked() ? CALicense : ui.rb_license_nonca->isChecked() ? NonCALicense : ""; - LDFile* f = LDFile::current(); - *f << new LDCommentObject (ui.le_title->text()); - *f << new LDCommentObject ("Name: <untitled>.dat" ); - *f << new LDCommentObject (fmt ("Author: %1", ui.le_author->text())); - *f << new LDCommentObject (fmt ("!LDRAW_ORG Unofficial_Part")); - - if (license != "") - *f << new LDCommentObject (license); - - *f << new LDEmptyObject; - *f << new LDBFCObject (BFCType); - *f << new LDEmptyObject; + LDFile::current()->addObjects ({ + new LDComment (ui.le_title->text()), + new LDComment ("Name: <untitled>.dat" ), + new LDComment (fmt ("Author: %1", ui.le_author->text())), + new LDComment (fmt ("!LDRAW_ORG Unofficial_Part")), + (license != "" ? + new LDComment (license) : + null), + new LDEmpty, + new LDBFC (BFCType), + new LDEmpty, + }); g_win->fullRefresh(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (NewFile, CTRL (N)) { newFile(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Open, CTRL (O)) { str name = QFileDialog::getOpenFileName (g_win, "Open File", "", "LDraw files (*.dat *.ldr)"); @@ -97,22 +122,19 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Save, CTRL (S)) { g_win->save (LDFile::current(), false); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (SaveAs, CTRL_SHIFT (S)) { g_win->save (LDFile::current(), true); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (SaveAll, CTRL (L)) { for (LDFile* file : g_loadedFiles) { if (file->implicit()) @@ -123,8 +145,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Close, CTRL (W)) { if (!LDFile::current()->safeToClose()) return; @@ -133,8 +154,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (CloseAll, 0) { if (!safeToCloseAll()) return; @@ -143,63 +163,79 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Settings, 0) { - ConfigDialog::staticDialog(); -} - -DEFINE_ACTION (SetLDrawPath, 0) { - LDrawPathDialog dlg (true); - dlg.exec(); + (new ConfigDialog)->exec(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ----------------------------------------------------------------------------- +DEFINE_ACTION (SetLDrawPath, 0) { + (new LDrawPathDialog (true))->exec(); +} + // ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Exit, CTRL (Q)) { exit (0); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (NewSubfile, 0) { AddObjectDialog::staticDialog (LDObject::Subfile, null); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (NewLine, 0) { AddObjectDialog::staticDialog (LDObject::Line, null); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (NewTriangle, 0) { AddObjectDialog::staticDialog (LDObject::Triangle, null); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (NewQuad, 0) { AddObjectDialog::staticDialog (LDObject::Quad, null); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (NewCLine, 0) { - AddObjectDialog::staticDialog (LDObject::CondLine, null); + AddObjectDialog::staticDialog (LDObject::CndLine, null); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (NewComment, 0) { AddObjectDialog::staticDialog (LDObject::Comment, null); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (NewBFC, 0) { AddObjectDialog::staticDialog (LDObject::BFC, null); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (NewVertex, 0) { AddObjectDialog::staticDialog (LDObject::Vertex, null); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (MakePrimitive, 0) { generatePrimitive(); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Edit, 0) { if (g_win->sel().size() != 1) return; @@ -208,34 +244,37 @@ AddObjectDialog::staticDialog (obj->getType(), obj); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Help, KEY (F1)) { } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (About, 0) { AboutDialog().exec(); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (AboutQt, 0) { QMessageBox::aboutQt (g_win); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (SelectAll, CTRL (A)) { g_win->sel().clear(); - for (LDObject* obj : LDFile::current()->objs()) + for (LDObject* obj : LDFile::current()->objects()) g_win->sel() << obj; g_win->updateSelection(); } // ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (SelectByColor, CTRL_SHIFT (A)) { short colnum = g_win->getSelectedColor(); @@ -243,7 +282,7 @@ return; // no consensus on color g_win->sel().clear(); - for (LDObject* obj : LDFile::current()->objs()) + for (LDObject* obj : LDFile::current()->objects()) if (obj->color() == colnum) g_win->sel() << obj; @@ -251,6 +290,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (SelectByType, 0) { if (g_win->sel().size() == 0) return; @@ -265,19 +305,19 @@ str refName; if (type == LDObject::Subfile) { - refName = static_cast<LDSubfileObject*> (g_win->sel()[0])->fileInfo()->name(); + refName = static_cast<LDSubfile*> (g_win->sel()[0])->fileInfo()->name(); for (LDObject* obj : g_win->sel()) - if (static_cast<LDSubfileObject*> (obj)->fileInfo()->name() != refName) + if (static_cast<LDSubfile*> (obj)->fileInfo()->name() != refName) return; } g_win->sel().clear(); - for (LDObject* obj : LDFile::current()->objs()) { + for (LDObject* obj : LDFile::current()->objects()) { if (obj->getType() != type) continue; - if (type == LDObject::Subfile && static_cast<LDSubfileObject*> (obj)->fileInfo()->name() != refName) + if (type == LDObject::Subfile && static_cast<LDSubfile*> (obj)->fileInfo()->name() != refName) continue; g_win->sel() << obj; @@ -287,8 +327,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (GridCoarse, 0) { grid = Grid::Coarse; g_win->updateGridToolBar(); @@ -305,16 +344,14 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (ResetView, CTRL (0)) { g_win->R()->resetAngles(); g_win->R()->update(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (InsertFrom, 0) { str fname = QFileDialog::getOpenFileName(); ulong idx = g_win->getInsertionPoint(); @@ -345,8 +382,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (ExportTo, 0) { if (g_win->sel().size() == 0) return; @@ -370,8 +406,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (InsertRaw, 0) { ulong idx = g_win->getInsertionPoint(); @@ -405,6 +440,8 @@ g_win->scrollToSelection(); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Screenshot, 0) { setlocale (LC_ALL, "C"); @@ -427,7 +464,8 @@ } // ============================================================================= -extern_cfg (bool, gl_axes); +// ----------------------------------------------------------------------------- +extern_cfg (Bool, gl_axes); DEFINE_ACTION (Axes, 0) { gl_axes = !gl_axes; ACTION (Axes)->setChecked (gl_axes); @@ -435,6 +473,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Visibility, 0) { for (LDObject* obj : g_win->sel()) obj->setHidden (!obj->hidden()); @@ -442,13 +481,16 @@ g_win->refresh(); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Wireframe, 0) { gl_wireframe = !gl_wireframe; g_win->R()->refresh(); } -DEFINE_ACTION (SetOverlay, 0) -{ +// ============================================================================= +// ----------------------------------------------------------------------------- +DEFINE_ACTION (SetOverlay, 0) { OverlayDialog dlg; if (!dlg.exec()) @@ -458,18 +500,26 @@ dlg.ofsy(), dlg.lwidth(), dlg.lheight() ); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (ClearOverlay, 0) { g_win->R()->clearOverlay(); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (ModeSelect, CTRL (1)) { g_win->R()->setEditMode (Select); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (ModeDraw, CTRL (2)) { g_win->R()->setEditMode (Draw); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (SetDrawDepth, 0) { if (g_win->R()->camera() == GL::Free) return; @@ -527,12 +577,37 @@ } #endif +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (ScanPrimitives, 0) { PrimitiveLister::start(); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (BFCView, SHIFT (B)) { gl_colorbfc = !gl_colorbfc; ACTION (BFCView)->setChecked (gl_colorbfc); g_win->R()->refresh(); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +DEFINE_ACTION (JumpTo, CTRL (G)) { + bool ok; + int defval = 0; + LDObject* obj; + + if (g_win->sel().size() == 1) + defval = g_win->sel()[0]->getIndex(); + + int idx = QInputDialog::getInt (null, "Go to line", "Go to line:", defval, + 1, LDFile::current()->numObjs(), 1, &ok); + + if (!ok || (obj = LDFile::current()->object (idx - 1)) == null) + return; + + g_win->clearSelection(); + g_win->sel() << obj; + g_win->updateSelection(); } \ No newline at end of file
--- a/src/gui_editactions.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/gui_editactions.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -33,12 +33,13 @@ #include "ui_replcoords.h" #include "ui_editraw.h" #include "ui_flip.h" +#include "ui_addhistoryline.h" -cfg (bool, edit_schemanticinline, false); +cfg (Bool, edit_schemanticinline, false); +extern_cfg (String, ld_defaultuser); // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static int copyToClipboard() { List<LDObject*> objs = g_win->sel(); int num = 0; @@ -62,8 +63,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Cut, CTRL (X)) { int num = copyToClipboard(); g_win->deleteSelection(); @@ -71,16 +71,14 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Copy, CTRL (C)) { int num = copyToClipboard(); log (ForgeWindow::tr ("%1 objects copied"), num); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Paste, CTRL (V)) { const str clipboardText = qApp->clipboard()->text(); ulong idx = g_win->getInsertionPoint(); @@ -101,16 +99,14 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Delete, KEY (Delete)) { int num = g_win->deleteSelection(); log (ForgeWindow::tr ("%1 objects deleted"), num); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static void doInline (bool deep) { List<LDObject*> sel = g_win->sel(); @@ -125,7 +121,11 @@ List<LDObject*> objs; if (obj->getType() == LDObject::Subfile) - objs = static_cast<LDSubfileObject*> (obj)->inlineContents (deep, true); + objs = static_cast<LDSubfile*> (obj)->inlineContents ( + (LDSubfile::InlineFlags) + ((deep) ? LDSubfile::DeepInline : 0) | + LDSubfile::CacheInline + ); else continue; @@ -156,9 +156,8 @@ doInline (true); } -// =============================================================================================== -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// =============================================================================================== +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (SplitQuads, 0) { List<LDObject*> objs = g_win->sel(); int num = 0; @@ -173,14 +172,14 @@ if (index == -1) return; - List<LDTriangleObject*> triangles = static_cast<LDQuadObject*> (obj)->splitToTriangles(); + List<LDTriangle*> triangles = static_cast<LDQuad*> (obj)->splitToTriangles(); // Replace the quad with the first triangle and add the second triangle // after the first one. LDFile::current()->setObject (index, triangles[0]); LDFile::current()->insertObj (index + 1, triangles[1]); - for (LDTriangleObject * t : triangles) + for (LDTriangle * t : triangles) g_win->R()->compileObject (t); // Delete this quad now, it has been split. @@ -194,8 +193,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (EditRaw, KEY (F9)) { if (g_win->sel().size() != 1) return; @@ -208,7 +206,7 @@ ui.code->setText (obj->raw()); if (obj->getType() == LDObject::Error) - ui.errorDescription->setText (static_cast<LDErrorObject*> (obj)->reason); + ui.errorDescription->setText (static_cast<LDError*> (obj)->reason); else { ui.errorDescription->hide(); ui.errorIcon->hide(); @@ -229,8 +227,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (SetColor, KEY (C)) { if (g_win->sel().size() <= 0) return; @@ -259,8 +256,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Borders, CTRL_SHIFT (B)) { List<LDObject*> objs = g_win->sel(); int num = 0; @@ -270,23 +266,23 @@ continue; short numLines; - LDLineObject* lines[4]; + LDLine* lines[4]; if (obj->getType() == LDObject::Quad) { numLines = 4; - LDQuadObject* quad = static_cast<LDQuadObject*> (obj); - lines[0] = new LDLineObject (quad->getVertex (0), quad->getVertex (1)); - lines[1] = new LDLineObject (quad->getVertex (1), quad->getVertex (2)); - lines[2] = new LDLineObject (quad->getVertex (2), quad->getVertex (3)); - lines[3] = new LDLineObject (quad->getVertex (3), quad->getVertex (0)); + LDQuad* quad = static_cast<LDQuad*> (obj); + lines[0] = new LDLine (quad->getVertex (0), quad->getVertex (1)); + lines[1] = new LDLine (quad->getVertex (1), quad->getVertex (2)); + lines[2] = new LDLine (quad->getVertex (2), quad->getVertex (3)); + lines[3] = new LDLine (quad->getVertex (3), quad->getVertex (0)); } else { numLines = 3; - LDTriangleObject* tri = static_cast<LDTriangleObject*> (obj); - lines[0] = new LDLineObject (tri->getVertex (0), tri->getVertex (1)); - lines[1] = new LDLineObject (tri->getVertex (1), tri->getVertex (2)); - lines[2] = new LDLineObject (tri->getVertex (2), tri->getVertex (0)); + LDTriangle* tri = static_cast<LDTriangle*> (obj); + lines[0] = new LDLine (tri->getVertex (0), tri->getVertex (1)); + lines[1] = new LDLine (tri->getVertex (1), tri->getVertex (2)); + lines[2] = new LDLine (tri->getVertex (2), tri->getVertex (0)); } for (short i = 0; i < numLines; ++i) { @@ -305,8 +301,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (CornerVerts, 0) { int num = 0; @@ -317,7 +312,7 @@ ulong idx = obj->getIndex(); for (short i = 0; i < obj->vertices(); ++i) { - LDVertexObject* vert = new LDVertexObject; + LDVertex* vert = new LDVertex; vert->pos = obj->getVertex (i); vert->setColor (obj->color()); @@ -332,14 +327,15 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static void doMoveSelection (const bool up) { List<LDObject*> objs = g_win->sel(); LDObject::moveObjects (objs, up); g_win->buildObjList(); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (MoveUp, KEY (PageUp)) { doMoveSelection (true); } @@ -349,8 +345,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Undo, CTRL (Z)) { LDFile::current()->undo(); } @@ -360,8 +355,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void doMoveObjects (vertex vect) { // Apply the grid values vect[X] *= currentGrid().confs[Grid::X]->value; @@ -376,8 +370,10 @@ g_win->refresh(); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (MoveXNeg, KEY (Left)) { - doMoveObjects ({ -1, 0, 0}); + doMoveObjects ({-1, 0, 0}); } DEFINE_ACTION (MoveYNeg, KEY (Home)) { @@ -401,6 +397,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Invert, CTRL_SHIFT (W)) { List<LDObject*> sel = g_win->sel(); @@ -413,34 +410,36 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- static void rotateVertex (vertex& v, const vertex& rotpoint, const matrix& transform) { v.move (-rotpoint); v.transform (transform, g_origin); v.move (rotpoint); } +// ============================================================================= +// ----------------------------------------------------------------------------- static void doRotate (const short l, const short m, const short n) { List<LDObject*> sel = g_win->sel(); List<vertex*> queue; const vertex rotpoint = rotPoint (sel); - const double angle = (pi * currentGrid().confs[Grid::Angle]->value) / 180; - - // ref: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation_2 - const double cosangle = cos (angle), + const double angle = (pi * currentGrid().confs[Grid::Angle]->value) / 180, + cosangle = cos (angle), sinangle = sin (angle); + // ref: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation_2 matrix transform ({ - (l* l * (1 - cosangle)) + cosangle, - (m* l * (1 - cosangle)) - (n* sinangle), - (n* l * (1 - cosangle)) + (m* sinangle), + (l * l * (1 - cosangle)) + cosangle, + (m * l * (1 - cosangle)) - (n * sinangle), + (n * l * (1 - cosangle)) + (m * sinangle), - (l* m * (1 - cosangle)) + (n* sinangle), - (m* m * (1 - cosangle)) + cosangle, - (n* m * (1 - cosangle)) - (l* sinangle), + (l * m * (1 - cosangle)) + (n * sinangle), + (m * m * (1 - cosangle)) + cosangle, + (n * m * (1 - cosangle)) - (l * sinangle), - (l* n * (1 - cosangle)) - (m* sinangle), - (m* n * (1 - cosangle)) + (l* sinangle), - (n* n * (1 - cosangle)) + cosangle + (l * n * (1 - cosangle)) - (m * sinangle), + (m * n * (1 - cosangle)) + (l * sinangle), + (n * n * (1 - cosangle)) + cosangle }); // Apply the above matrix to everything @@ -453,12 +452,16 @@ } } elif (obj->hasMatrix()) { LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (obj); + + // Transform the position vertex v = mo->position(); rotateVertex (v, rotpoint, transform); mo->setPosition (v); + + // Transform the matrix mo->setTransform (mo->transform() * transform); } elif (obj->getType() == LDObject::Vertex) { - LDVertexObject* vert = static_cast<LDVertexObject*> (obj); + LDVertex* vert = static_cast<LDVertex*> (obj); vertex v = vert->pos; rotateVertex (v, rotpoint, transform); vert->pos = v; @@ -470,6 +473,8 @@ g_win->refresh(); } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (RotateXPos, CTRL (Right)) { doRotate (1, 0, 0); } DEFINE_ACTION (RotateYPos, CTRL (End)) { doRotate (0, 1, 0); } DEFINE_ACTION (RotateZPos, CTRL (Up)) { doRotate (0, 0, 1); } @@ -482,8 +487,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (RoundCoordinates, 0) { setlocale (LC_ALL, "C"); int num = 0; @@ -509,8 +513,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Uncolorize, 0) { int num = 0; @@ -520,7 +523,7 @@ int col = maincolor; - if (obj->getType() == LDObject::Line || obj->getType() == LDObject::CondLine) + if (obj->getType() == LDObject::Line || obj->getType() == LDObject::CndLine) col = edgecolor; obj->setColor (col); @@ -533,6 +536,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (ReplaceCoords, CTRL (R)) { QDialog* dlg = new QDialog (g_win); Ui::ReplaceCoordsUI ui; @@ -577,7 +581,8 @@ g_win->refresh(); } -// ================================================================================================ +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Flip, CTRL_SHIFT (F)) { QDialog* dlg = new QDialog; Ui::FlipUI ui; @@ -605,16 +610,17 @@ g_win->refresh(); } -// ================================================================================================ +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Demote, 0) { List<LDObject*> sel = g_win->sel(); int num = 0; for (LDObject* obj : sel) { - if (obj->getType() != LDObject::CondLine) + if (obj->getType() != LDObject::CndLine) continue; - LDLineObject* repl = static_cast<LDCondLineObject*> (obj)->demote(); + LDLine* repl = static_cast<LDCndLine*> (obj)->demote(); g_win->R()->compileObject (repl); ++num; } @@ -623,15 +629,18 @@ g_win->refresh(); } -// ================================================================================================= +// ============================================================================= +// ----------------------------------------------------------------------------- static bool isColorUsed (short colnum) { - for (LDObject* obj : LDFile::current()->objs()) + for (LDObject* obj : LDFile::current()->objects()) if (obj->isColored() && obj->color() == colnum) return true; return false; } +// ============================================================================= +// ----------------------------------------------------------------------------- DEFINE_ACTION (Autocolor, 0) { short colnum = 0; @@ -639,8 +648,7 @@ colnum++; if (colnum >= MAX_COLORS) { - //: Auto-colorer error message - critical (ForgeWindow::tr ("Out of unused colors! What are you doing?!")); + log (ForgeWindow::tr ("Cannot auto-color: all colors are in use!")); return; } @@ -654,4 +662,60 @@ log (ForgeWindow::tr ("Auto-colored: new color is [%1] %2"), colnum, getColor (colnum)->name); g_win->refresh(); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +DEFINE_ACTION (AddHistoryLine, 0) { + LDObject* obj; + bool ishistory = false, + prevIsHistory = false; + + QDialog* dlg = new QDialog; + Ui_AddHistoryLine* ui = new Ui_AddHistoryLine; + ui->setupUi (dlg); + ui->m_username->setText (ld_defaultuser); + ui->m_date->setDate (QDate::currentDate()); + ui->m_comment->setFocus(); + + if (!dlg->exec()) + return; + + // Create the comment object based on input + str commentText = fmt ("!HISTORY %1 [%2] %3", + ui->m_date->date().toString("yyyy-MM-dd"), + ui->m_username->text(), + ui->m_comment->text()); + + LDComment* comm = new LDComment (commentText); + + // Find a spot to place the new comment + for ( + obj = LDFile::current()->object (0); + obj && obj->next() && !obj->next()->isScemantic(); + obj = obj->next() + ) { + LDComment* comm = dynamic_cast<LDComment*> (obj); + if (comm && comm->text.startsWith ("!HISTORY ")) + ishistory = true; + + if (prevIsHistory && !ishistory) { + // Last line was history, this isn't, thus insert the new history + // line here. + break; + } + + prevIsHistory = ishistory; + } + + int idx = obj ? obj->getIndex() : 0; + LDFile::current()->insertObj (idx++, comm); + + // If we're adding a history line right before a scemantic object, pad it + // an empty line + if (obj && obj->next() && obj->next()->isScemantic()) + LDFile::current()->insertObj (idx, new LDEmpty); + + g_win->buildObjList(); + delete ui; } \ No newline at end of file
--- a/src/history.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/history.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -25,10 +25,14 @@ bool g_fullRefresh = false; +// ============================================================================= +// ----------------------------------------------------------------------------- History::History() : m_pos (-1), m_opened (false) {} +// ============================================================================= +// ----------------------------------------------------------------------------- void History::undo() { if (m_changesets.size() == 0 || pos() == -1) return; @@ -50,6 +54,8 @@ updateActions(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void History::redo() { if (pos() == (long) m_changesets.size()) return; @@ -71,6 +77,8 @@ updateActions(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void History::clear() { for (List<AbstractHistoryEntry*> set : m_changesets) for (AbstractHistoryEntry * change : set) @@ -79,11 +87,15 @@ m_changesets.clear(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void History::updateActions() const { ACTION (Undo)->setEnabled (pos() != -1); ACTION (Redo)->setEnabled (pos() < (long) m_changesets.size() - 1); } +// ============================================================================= +// ----------------------------------------------------------------------------- void History::open() { if (opened()) return; @@ -91,6 +103,8 @@ setOpened (true); } +// ============================================================================= +// ----------------------------------------------------------------------------- void History::close() { if (!opened()) return; @@ -109,6 +123,8 @@ updateActions(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void History::add (AbstractHistoryEntry* entry) { if (!opened()) { delete entry; @@ -120,6 +136,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void AddHistory::undo() const { LDFile* f = parent()->file(); LDObject* obj = f->object (index()); @@ -129,6 +146,8 @@ g_fullRefresh = true; } +// ============================================================================= +// ----------------------------------------------------------------------------- void AddHistory::redo() const { LDFile* f = parent()->file(); LDObject* obj = parseLine (code()); @@ -140,6 +159,7 @@ // ============================================================================= // heh +// ----------------------------------------------------------------------------- void DelHistory::undo() const { LDFile* f = parent()->file(); LDObject* obj = parseLine (code()); @@ -147,6 +167,8 @@ g_win->R()->compileObject (obj); } +// ============================================================================= +// ----------------------------------------------------------------------------- void DelHistory::redo() const { LDFile* f = parent()->file(); LDObject* obj = f->object (index()); @@ -159,6 +181,7 @@ DelHistory::~DelHistory() {} // ============================================================================= +// ----------------------------------------------------------------------------- void EditHistory::undo() const { LDObject* obj = LDFile::current()->object (index()); LDObject* newobj = parseLine (oldCode()); @@ -166,6 +189,8 @@ g_win->R()->compileObject (newobj); } +// ============================================================================= +// ----------------------------------------------------------------------------- void EditHistory::redo() const { LDObject* obj = LDFile::current()->object (index()); LDObject* newobj = parseLine (newCode()); @@ -176,6 +201,7 @@ EditHistory::~EditHistory() {} // ============================================================================= +// ----------------------------------------------------------------------------- void SwapHistory::undo() const { LDObject::fromID (a)->swap (LDObject::fromID (b)); }
--- a/src/history.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/history.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */
--- a/src/labeledwidget.h Fri Aug 16 11:05:21 2013 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * LDForge: LDraw parts authoring CAD - * Copyright (C) 2013 Santeri Piippo - * - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef LABELEDWIDGET_H -#define LABELEDWIDGET_H - -#include "common.h" -#include <QLabel> -#include <QBoxLayout> - -// ============================================================================= -// LabeledWidget -// -// Convenience class for a widget with a label beside it. -// ============================================================================= -template<class R> class LabeledWidget : public QWidget { - PROPERTY (QLabel*, label, setLabel) - PROPERTY (R*, widget, setWidget) - -public: - explicit LabeledWidget (const char* labelstr, QWidget* parent = null) : QWidget (parent) { - m_widget = new R (this); - commonInit (labelstr); - } - - explicit LabeledWidget (const char* labelstr, R* widget, QWidget* parent = null) : - QWidget (parent), m_widget (widget) { - - commonInit (labelstr); - } - - explicit LabeledWidget (QWidget* parent = 0, Qt::WindowFlags f = 0) { - m_widget = new R (this); - commonInit (""); - } - - R* w() const { return m_widget; } - operator R*() { return m_widget; } - -private: - Q_DISABLE_COPY (LabeledWidget<R>) - - void commonInit (const char* labelstr) { - m_label = new QLabel (labelstr, this); - m_layout = new QHBoxLayout; - m_layout->addWidget (m_label); - m_layout->addWidget (m_widget); - setLayout (m_layout); - } - - QHBoxLayout* m_layout; -}; - -#endif // LABELEDWIDGET_H \ No newline at end of file
--- a/src/ldconfig.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/ldconfig.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -24,6 +24,7 @@ // ============================================================================= // Helper function for parseLDConfig +// ----------------------------------------------------------------------------- static bool parseLDConfigTag (LDConfigParser& pars, char const* tag, str& val) { short pos; @@ -36,13 +37,13 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void parseLDConfig() { File* f = openLDrawFile ("LDConfig.ldr", false); if (!f) { critical (fmt (QObject::tr ("Unable to open LDConfig.ldr for parsing! (%1)"), strerror (errno))); - delete f; return; } @@ -110,23 +111,25 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- LDConfigParser::LDConfigParser (str inText, char sep) { m_tokens = container_cast<QStringList, List<str>> (inText.split (sep, QString::SkipEmptyParts)); m_pos = -1; } +// ============================================================================= // ----------------------------------------------------------------------------- bool LDConfigParser::atBeginning() { return (m_pos == -1); } +// ============================================================================= // ----------------------------------------------------------------------------- bool LDConfigParser::atEnd() { return (m_pos == (signed) m_tokens.size() - 1); } +// ============================================================================= // ----------------------------------------------------------------------------- bool LDConfigParser::getToken (str& val, const ushort pos) { if (pos >= m_tokens.size()) @@ -136,16 +139,19 @@ return true; } +// ============================================================================= // ----------------------------------------------------------------------------- bool LDConfigParser::next (str& val) { return getToken (val, ++m_pos); } +// ============================================================================= // ----------------------------------------------------------------------------- bool LDConfigParser::peekNext (str& val) { return getToken (val, m_pos + 1); } +// ============================================================================= // ----------------------------------------------------------------------------- bool LDConfigParser::findToken (short& result, char const* needle, short args) { for (ushort i = 0; i < (m_tokens.size() - args); ++i) { @@ -158,21 +164,25 @@ return false; } +// ============================================================================= // ----------------------------------------------------------------------------- void LDConfigParser::rewind() { m_pos = -1; } +// ============================================================================= // ----------------------------------------------------------------------------- void LDConfigParser::seek (short amount, bool rel) { m_pos = (rel ? m_pos : 0) + amount; } +// ============================================================================= // ----------------------------------------------------------------------------- size_t LDConfigParser::size() { return m_tokens.size(); } +// ============================================================================= // ----------------------------------------------------------------------------- bool LDConfigParser::tokenCompare (short inPos, const char* sOther) { str tok;
--- a/src/ldtypes.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/ldtypes.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -25,21 +25,24 @@ #include "gldraw.h" #include "colors.h" +cfg (String, ld_defaultname, ""); +cfg (String, ld_defaultuser, ""); +cfg (Int, ld_defaultlicense, 0); + // List of all LDObjects List<LDObject*> g_LDObjects; // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= // LDObject constructors +// ----------------------------------------------------------------------------- LDObject::LDObject() : m_hidden (false), m_selected (false), m_parent (null), m_file (null), qObjListEntry (null), - m_glinit (false) { - + m_glinit (false) +{ // Determine ID int32 id = 1; // 0 is invalid @@ -51,9 +54,11 @@ g_LDObjects << this; } +// ============================================================================= // Default implementations for LDObject's virtual methods. These should never be // actually called, for a subclass-less LDObject should never come into existance. // These exist only to satisfy the linker. +// ----------------------------------------------------------------------------- LDObject::Type LDObject::getType() const { return LDObject::Unidentified; } @@ -79,20 +84,24 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void LDObject::setVertexCoord (int i, Axis ax, double value) { vertex v = getVertex (i); v[ax] = value; setVertex (i, v); } -LDErrorObject::LDErrorObject() {} +LDError::LDError() {} // ============================================================================= -str LDCommentObject::raw() { +// ----------------------------------------------------------------------------- +str LDComment::raw() { return fmt ("0 %1", text); } -str LDSubfileObject::raw() { +// ============================================================================= +// ----------------------------------------------------------------------------- +str LDSubfile::raw() { str val = fmt ("1 %1 %2 ", color(), position()); val += transform().stringRep(); val += ' '; @@ -100,7 +109,9 @@ return val; } -str LDLineObject::raw() { +// ============================================================================= +// ----------------------------------------------------------------------------- +str LDLine::raw() { str val = fmt ("2 %1", color()); for (ushort i = 0; i < 2; ++i) @@ -109,7 +120,9 @@ return val; } -str LDTriangleObject::raw() { +// ============================================================================= +// ----------------------------------------------------------------------------- +str LDTriangle::raw() { str val = fmt ("3 %1", color()); for (ushort i = 0; i < 3; ++i) @@ -118,7 +131,9 @@ return val; } -str LDQuadObject::raw() { +// ============================================================================= +// ----------------------------------------------------------------------------- +str LDQuad::raw() { str val = fmt ("4 %1", color()); for (ushort i = 0; i < 4; ++i) @@ -127,7 +142,9 @@ return val; } -str LDCondLineObject::raw() { +// ============================================================================= +// ----------------------------------------------------------------------------- +str LDCndLine::raw() { str val = fmt ("5 %1", color()); // Add the coordinates @@ -137,22 +154,27 @@ return val; } -str LDErrorObject::raw() { +// ============================================================================= +// ----------------------------------------------------------------------------- +str LDError::raw() { return contents; } -str LDVertexObject::raw() { +// ============================================================================= +// ----------------------------------------------------------------------------- +str LDVertex::raw() { return fmt ("0 !LDFORGE VERTEX %1 %2", color(), pos); } -str LDEmptyObject::raw() { +// ============================================================================= +// ----------------------------------------------------------------------------- +str LDEmpty::raw() { return ""; } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -const char* LDBFCObject::statements[] = { +// ----------------------------------------------------------------------------- +const char* LDBFC::statements[] = { "CERTIFY CCW", "CCW", "CERTIFY CW", @@ -165,66 +187,70 @@ "NOCLIP", }; -str LDBFCObject::raw() { - return fmt ("0 BFC %1", LDBFCObject::statements[type]); +str LDBFC::raw() { + return fmt ("0 BFC %1", LDBFC::statements[type]); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -List<LDTriangleObject*> LDQuadObject::splitToTriangles() { +// ----------------------------------------------------------------------------- +List<LDTriangle*> LDQuad::splitToTriangles() { // Create the two triangles based on this quadrilateral: // 0---3 0---3 3 // | | | / /| // | | ==> | / / | // | | |/ / | // 1---2 1 1---2 - LDTriangleObject* tri1 = new LDTriangleObject (getVertex (0), getVertex (1), getVertex (3)); - LDTriangleObject* tri2 = new LDTriangleObject (getVertex (1), getVertex (2), getVertex (3)); + LDTriangle* tri1 = new LDTriangle (getVertex (0), getVertex (1), getVertex (3)); + LDTriangle* tri2 = new LDTriangle (getVertex (1), getVertex (2), getVertex (3)); // The triangles also inherit the quad's color tri1->setColor (color()); tri2->setColor (color()); - List<LDTriangleObject*> triangles; + List<LDTriangle*> triangles; triangles << tri1; triangles << tri2; return triangles; } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDObject::replace (LDObject* other) { long idx = getIndex(); assert (idx != -1); // Replace the instance of the old object with the new object - LDFile::current()->setObject (idx, other); + file()->setObject (idx, other); // Remove the old object delete this; } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDObject::swap (LDObject* other) { - for (LDObject*& obj : *LDFile::current()) { + int i = 0; + for (LDObject* obj : file()->objects()) { if (obj == this) - obj = other; + file()->setObject (i, other); elif (obj == other) - obj = this; + file()->setObject (i, this); + + ++i; } - LDFile::current()->addToHistory (new SwapHistory (id(), other->id())); + file()->addToHistory (new SwapHistory (id(), other->id())); } -LDLineObject::LDLineObject (vertex v1, vertex v2) { +// ============================================================================= +// ----------------------------------------------------------------------------- +LDLine::LDLine (vertex v1, vertex v2) { setVertex (0, v1); setVertex (1, v2); } +// ============================================================================= +// ----------------------------------------------------------------------------- LDObject::~LDObject() { // Remove this object from the selection array if it is there. for (ulong i = 0; i < g_win->sel().size(); ++i) @@ -242,12 +268,11 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static void transformObject (LDObject* obj, matrix transform, vertex pos, short parentcolor) { switch (obj->getType()) { case LDObject::Line: - case LDObject::CondLine: + case LDObject::CndLine: case LDObject::Triangle: case LDObject::Quad: for (short i = 0; i < obj->vertices(); ++i) { @@ -260,7 +285,7 @@ case LDObject::Subfile: { - LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); + LDSubfile* ref = static_cast<LDSubfile*> (obj); matrix newMatrix = transform * ref->transform(); vertex newpos = ref->position(); @@ -279,50 +304,9 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -List<LDObject*> LDSubfileObject::inlineContents (bool deep, bool cache) { - List<LDObject*> objs, objcache; - - // If we have this cached, just clone that - if (deep && fileInfo()->cache().size()) { - for (LDObject* obj : fileInfo()->cache()) - objs << obj->clone(); - } else { - if (!deep) - cache = false; - - for (LDObject* obj : *fileInfo()) { - // Skip those without scemantic meaning - if (!obj->isScemantic()) - continue; - - // Got another sub-file reference, inline it if we're deep-inlining. If not, - // just add it into the objects normally. Also, we only cache immediate - // subfiles and this is not one. Yay, recursion! - if (deep && obj->getType() == LDObject::Subfile) { - LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); - - List<LDObject*> otherobjs = ref->inlineContents (true, false); - - for (LDObject* otherobj : otherobjs) { - // Cache this object, if desired - if (cache) - objcache << otherobj->clone(); - - objs << otherobj; - } - } else { - if (cache) - objcache << obj->clone(); - - objs << obj->clone(); - } - } - - if (cache) - fileInfo()->setCache (objcache); - } +// ----------------------------------------------------------------------------- +List<LDObject*> LDSubfile::inlineContents (InlineFlags flags) { + List<LDObject*> objs = fileInfo()->inlineContents (flags); // Transform the objects for (LDObject* obj : objs) { @@ -335,8 +319,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- long LDObject::getIndex() const { #ifndef RELEASE assert (file() != null); @@ -350,14 +333,17 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDObject::moveObjects (List<LDObject*> objs, const bool up) { + if (objs.size() == 0) + return; + // If we move down, we need to iterate the array in reverse order. const long start = up ? 0 : (objs.size() - 1); const long end = up ? objs.size() : -1; const long incr = up ? 1 : -1; List<LDObject*> objsToCompile; + LDFile* file = objs[0]->file(); for (long i = start; i != end; i += incr) { LDObject* obj = objs[i]; @@ -365,7 +351,7 @@ const long idx = obj->getIndex(), target = idx + (up ? -1 : 1); - if ((up && idx == 0) || (!up && idx == (long) (LDFile::current()->objs().size() - 1))) { + if ((up && idx == 0) || (!up && idx == (long) (file->objects().size() - 1))) { // One of the objects hit the extrema. If this happens, this should be the first // object to be iterated on. Thus, nothing has changed yet and it's safe to just // abort the entire operation. @@ -374,9 +360,9 @@ } objsToCompile << obj; - objsToCompile << LDFile::current()->obj (target); + objsToCompile << file->obj (target); - obj->swap (LDFile::current()->obj (target)); + obj->swap (file->obj (target)); } objsToCompile.makeUnique(); @@ -387,6 +373,8 @@ g_win->R()->compileObject (obj); } +// ============================================================================= +// ----------------------------------------------------------------------------- str LDObject::typeName (LDObject::Type type) { LDObject* obj = LDObject::getDefault (type); str name = obj->typeName(); @@ -395,8 +383,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- str LDObject::objectListContents (const List<LDObject*>& objs) { bool firstDetails = true; str text = ""; @@ -432,6 +419,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- LDObject* LDObject::topLevelParent() { if (!parent()) return this; @@ -445,17 +433,19 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- LDObject* LDObject::next() const { long idx = getIndex(); assert (idx != -1); - if (idx == (long) LDFile::current()->numObjs() - 1) + if (idx == (long) file()->numObjs() - 1) return null; - return LDFile::current()->obj (idx + 1); + return file()->obj (idx + 1); } // ============================================================================= +// ----------------------------------------------------------------------------- LDObject* LDObject::prev() const { long idx = getIndex(); assert (idx != -1); @@ -463,58 +453,68 @@ if (idx == 0) return null; - return LDFile::current()->obj (idx - 1); + return file()->obj (idx - 1); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDObject::move (vertex vect) { (void) vect; } -void LDEmptyObject::move (vertex vect) { (void) vect; } -void LDBFCObject::move (vertex vect) { (void) vect; } -void LDCommentObject::move (vertex vect) { (void) vect; } -void LDErrorObject::move (vertex vect) { (void) vect; } +void LDEmpty::move (vertex vect) { (void) vect; } +void LDBFC::move (vertex vect) { (void) vect; } +void LDComment::move (vertex vect) { (void) vect; } +void LDError::move (vertex vect) { (void) vect; } -void LDVertexObject::move (vertex vect) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDVertex::move (vertex vect) { pos += vect; } -void LDSubfileObject::move (vertex vect) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDSubfile::move (vertex vect) { setPosition (position() + vect); } -void LDLineObject::move (vertex vect) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDLine::move (vertex vect) { for (short i = 0; i < 2; ++i) setVertex (i, getVertex (i) + vect); } -void LDTriangleObject::move (vertex vect) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDTriangle::move (vertex vect) { for (short i = 0; i < 3; ++i) setVertex (i, getVertex (i) + vect); } -void LDQuadObject::move (vertex vect) { - for (short i = 0; i < 4; ++i) - setVertex (i, getVertex (i) + vect); -} - -void LDCondLineObject::move (vertex vect) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDQuad::move (vertex vect) { for (short i = 0; i < 4; ++i) setVertex (i, getVertex (i) + vect); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ----------------------------------------------------------------------------- +void LDCndLine::move (vertex vect) { + for (short i = 0; i < 4; ++i) + setVertex (i, getVertex (i) + vect); +} + // ============================================================================= +// ----------------------------------------------------------------------------- #define CHECK_FOR_OBJ(N) \ if (type == LDObject::N) \ - return new LD##N##Object; + return new LD##N; LDObject* LDObject::getDefault (const LDObject::Type type) { CHECK_FOR_OBJ (Comment) CHECK_FOR_OBJ (BFC) CHECK_FOR_OBJ (Line) - CHECK_FOR_OBJ (CondLine) + CHECK_FOR_OBJ (CndLine) CHECK_FOR_OBJ (Subfile) CHECK_FOR_OBJ (Triangle) CHECK_FOR_OBJ (Quad) @@ -527,15 +527,16 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDObject::invert() {} -void LDBFCObject::invert() {} -void LDEmptyObject::invert() {} -void LDCommentObject::invert() {} -void LDErrorObject::invert() {} +void LDBFC::invert() {} +void LDEmpty::invert() {} +void LDComment::invert() {} +void LDError::invert() {} -void LDTriangleObject::invert() { +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDTriangle::invert() { // Triangle goes 0 -> 1 -> 2, reversed: 0 -> 2 -> 1. // Thus, we swap 1 and 2. vertex tmp = getVertex (1); @@ -545,7 +546,9 @@ return; } -void LDQuadObject::invert() { +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDQuad::invert() { // Quad: 0 -> 1 -> 2 -> 3 // rev: 0 -> 3 -> 2 -> 1 // Thus, we swap 1 and 3. @@ -554,7 +557,9 @@ setVertex (3, tmp); } -void LDSubfileObject::invert() { +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDSubfile::invert() { // Subfiles are inverted when they're prefixed with // a BFC INVERTNEXT statement. Thus we need to toggle this status. // For flat primitives it's sufficient that the determinant is @@ -564,21 +569,23 @@ ulong idx = getIndex(); if (idx > 0) { - LDBFCObject* bfc = dynamic_cast<LDBFCObject*> (prev()); + LDBFC* bfc = dynamic_cast<LDBFC*> (prev()); - if (bfc && bfc->type == LDBFCObject::InvertNext) { + if (bfc && bfc->type == LDBFC::InvertNext) { // This is prefixed with an invertnext, thus remove it. - LDFile::current()->forgetObject (bfc); + file()->forgetObject (bfc); delete bfc; return; } } // Not inverted, thus prefix it with a new invertnext. - LDBFCObject* bfc = new LDBFCObject (LDBFCObject::InvertNext); - LDFile::current()->insertObj (idx, bfc); + LDBFC* bfc = new LDBFC (LDBFC::InvertNext); + file()->insertObj (idx, bfc); } +// ============================================================================= +// ----------------------------------------------------------------------------- static void invertLine (LDObject* line) { // For lines, we swap the vertices. I don't think that a // cond-line's control points need to be swapped, do they? @@ -587,19 +594,20 @@ line->setVertex (1, tmp); } -void LDLineObject::invert() { +void LDLine::invert() { invertLine (this); } -void LDCondLineObject::invert() { +void LDCndLine::invert() { invertLine (this); } -void LDVertexObject::invert() {} +void LDVertex::invert() {} // ============================================================================= -LDLineObject* LDCondLineObject::demote() { - LDLineObject* repl = new LDLineObject; +// ----------------------------------------------------------------------------- +LDLine* LDCndLine::demote() { + LDLine* repl = new LDLine; for (int i = 0; i < repl->vertices(); ++i) repl->setVertex (i, getVertex (i)); @@ -610,6 +618,8 @@ return repl; } +// ============================================================================= +// ----------------------------------------------------------------------------- LDObject* LDObject::fromID (int id) { for (LDObject* obj : g_LDObjects) if (obj->id() == id) @@ -619,21 +629,23 @@ } // ============================================================================= -str LDOverlayObject::raw() { +// ----------------------------------------------------------------------------- +str LDOverlay::raw() { return fmt ("0 !LDFORGE OVERLAY %1 %2 %3 %4 %5 %6", filename(), camera(), x(), y(), width(), height()); } -void LDOverlayObject::move (vertex vect) { +void LDOverlay::move (vertex vect) { Q_UNUSED (vect) } -void LDOverlayObject::invert() {} +void LDOverlay::invert() {} // ============================================================================= // Hook the set accessors of certain properties to this changeProperty function. // It takes care of history management so we can capture low-level changes, this // makes history stuff work out of the box. +// ----------------------------------------------------------------------------- template<class T> void changeProperty (LDObject* obj, T* ptr, const T& val) { long idx; @@ -642,11 +654,13 @@ *ptr = val; str after = obj->raw(); - LDFile::current()->addToHistory (new EditHistory (idx, before, after)); + obj->file()->addToHistory (new EditHistory (idx, before, after)); } else *ptr = val; } +// ============================================================================= +// ----------------------------------------------------------------------------- READ_ACCESSOR (short, LDObject::color) { return m_color; } @@ -655,6 +669,8 @@ changeProperty (this, &m_color, val); } +// ============================================================================= +// ----------------------------------------------------------------------------- const vertex& LDObject::getVertex (int i) const { return m_coords[i]; } @@ -663,6 +679,8 @@ changeProperty (this, &m_coords[i], vert); } +// ============================================================================= +// ----------------------------------------------------------------------------- READ_ACCESSOR (vertex, LDMatrixObject::position) { return m_position; } @@ -671,6 +689,8 @@ changeProperty (linkPointer(), &m_position, val); } +// ============================================================================= +// ----------------------------------------------------------------------------- READ_ACCESSOR (matrix, LDMatrixObject::transform) { return m_transform; }
--- a/src/ldtypes.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/ldtypes.h Sat Sep 07 13:23:09 2013 +0300 @@ -24,15 +24,15 @@ #define LDOBJ(T) \ public: \ - virtual ~LD##T##Object() {} \ + virtual ~LD##T() {} \ virtual LDObject::Type getType() const override { \ return LDObject::T; \ } \ virtual str raw(); \ - virtual LD##T##Object* clone() { \ - return new LD##T##Object (*this); \ + virtual LD##T* clone() { \ + return new LD##T (*this); \ } \ - virtual void move (vertex vVector); \ + virtual void move (vertex where); \ virtual void invert(); #define LDOBJ_NAME(N) virtual str typeName() const override { return #N; } @@ -50,7 +50,7 @@ #define LDOBJ_NO_MATRIX LDOBJ_SETMATRIX (false) class QListWidgetItem; -class LDSubfileObject; +class LDSubfile; class LDFile; // ============================================================================= @@ -76,7 +76,7 @@ Quad, // Object represents a quadrilateral Triangle, // Object represents a triangle Line, // Object represents a line - CondLine, // Object represents a conditional line + CndLine, // Object represents a conditional line Vertex, // Object is a vertex, LDForge extension object BFC, // Object represents a BFC statement Overlay, // Object contains meta-info about an overlay image. @@ -166,14 +166,14 @@ }; // ============================================================================= -// LDErrorObject +// LDError // // Represents a line in the LDraw file that could not be properly parsed. It is // represented by a (!) ERROR in the code view. It exists for the purpose of // allowing garbage lines be debugged and corrected within LDForge. The member // zContent contains the contents of the unparsable line. // ============================================================================= -class LDErrorObject : public LDObject { +class LDError : public LDObject { LDOBJ (Error) LDOBJ_NAME (error) LDOBJ_VERTICES (0) @@ -183,8 +183,8 @@ PROPERTY (str, fileRef, setFileRef) public: - LDErrorObject(); - LDErrorObject (str contents, str reason) : contents (contents), reason (reason) {} + LDError(); + LDError (str contents, str reason) : contents (contents), reason (reason) {} // Content of this unknown line str contents; @@ -194,11 +194,11 @@ }; // ============================================================================= -// LDEmptyObject +// LDEmpty // // Represents an empty line in the LDraw code file. // ============================================================================= -class LDEmptyObject : public LDObject { +class LDEmpty : public LDObject { LDOBJ (Empty) LDOBJ_VERTICES (0) LDOBJ_UNCOLORED @@ -207,12 +207,12 @@ }; // ============================================================================= -// LDCommentObject +// LDComment // // Represents a code-0 comment in the LDraw code file. Member text contains // the text of the comment. // ============================================================================= -class LDCommentObject : public LDObject { +class LDComment : public LDObject { LDOBJ (Comment) LDOBJ_NAME (comment) LDOBJ_VERTICES (0) @@ -221,19 +221,19 @@ LDOBJ_NO_MATRIX public: - LDCommentObject() {} - LDCommentObject (str text) : text (text) {} + LDComment() {} + LDComment (str text) : text (text) {} str text; // The text of this comment }; // ============================================================================= -// LDBFCObject +// LDBFC // // Represents a 0 BFC statement in the LDraw code. eStatement contains the type // of this statement. // ============================================================================= -class LDBFCObject : public LDObject { +class LDBFC : public LDObject { public: enum Type { CertifyCCW, @@ -257,8 +257,8 @@ LDOBJ_NO_MATRIX public: - LDBFCObject() {} - LDBFCObject (const LDBFCObject::Type type) : type (type) {} + LDBFC() {} + LDBFC (const LDBFC::Type type) : type (type) {} // Statement strings static const char* statements[]; @@ -267,11 +267,11 @@ }; // ============================================================================= -// LDSubfileObject +// LDSubfile // // Represents a single code-1 subfile reference. // ============================================================================= -class LDSubfileObject : public LDObject, public LDMatrixObject { +class LDSubfile : public LDObject, public LDMatrixObject { LDOBJ (Subfile) LDOBJ_NAME (subfile) LDOBJ_VERTICES (0) @@ -281,23 +281,35 @@ PROPERTY (LDFile*, fileInfo, setFileInfo) public: - LDSubfileObject() { + enum InlineFlag { + DeepInline = (1 << 0), + CacheInline = (1 << 1), + RendererInline = (1 << 2), + + DeepCacheInline = DeepInline | CacheInline, + }; + + Q_DECLARE_FLAGS (InlineFlags, InlineFlag) + + LDSubfile() { setLinkPointer (this); } - + // Inlines this subfile. Note that return type is an array of heap-allocated // LDObject-clones, they must be deleted one way or another. - List<LDObject*> inlineContents (bool deep, bool cache); + List<LDObject*> inlineContents (InlineFlags flags); }; +Q_DECLARE_OPERATORS_FOR_FLAGS (LDSubfile::InlineFlags) + // ============================================================================= -// LDLineObject +// LDLine // // Represents a single code-2 line in the LDraw code file. v0 and v1 are the end // points of the line. The line is colored with dColor unless uncolored mode is // set. // ============================================================================= -class LDLineObject : public LDObject { +class LDLine : public LDObject { LDOBJ (Line) LDOBJ_NAME (line) LDOBJ_VERTICES (2) @@ -306,18 +318,18 @@ LDOBJ_NO_MATRIX public: - LDLineObject() {} - LDLineObject (vertex v1, vertex v2); + LDLine() {} + LDLine (vertex v1, vertex v2); }; // ============================================================================= -// LDCondLineObject +// LDCndLine // // Represents a single code-5 conditional line. The end-points v0 and v1 are // inherited from LDLine, c0 and c1 are the control points of this line. // ============================================================================= -class LDCondLineObject : public LDLineObject { - LDOBJ (CondLine) +class LDCndLine : public LDLine { + LDOBJ (CndLine) LDOBJ_NAME (condline) LDOBJ_VERTICES (4) LDOBJ_COLORED @@ -325,18 +337,18 @@ LDOBJ_NO_MATRIX public: - LDCondLineObject() {} - LDLineObject* demote(); + LDCndLine() {} + LDLine* demote(); }; // ============================================================================= -// LDTriangleObject +// LDTriangle // // Represents a single code-3 triangle in the LDraw code file. Vertices v0, v1 // and v2 contain the end-points of this triangle. dColor is the color the // triangle is colored with. // ============================================================================= -class LDTriangleObject : public LDObject { +class LDTriangle : public LDObject { LDOBJ (Triangle) LDOBJ_NAME (triangle) LDOBJ_VERTICES (3) @@ -345,8 +357,8 @@ LDOBJ_NO_MATRIX public: - LDTriangleObject() {} - LDTriangleObject (vertex v0, vertex v1, vertex v2) { + LDTriangle() {} + LDTriangle (vertex v0, vertex v1, vertex v2) { setVertex (0, v0); setVertex (1, v1); setVertex (2, v2); @@ -354,12 +366,12 @@ }; // ============================================================================= -// LDQuadObject +// LDQuad // // Represents a single code-4 quadrilateral. v0, v1, v2 and v3 are the end points // of the quad, dColor is the color used for the quad. // ============================================================================= -class LDQuadObject : public LDObject { +class LDQuad : public LDObject { public: LDOBJ (Quad) LDOBJ_NAME (quad) @@ -368,21 +380,21 @@ LDOBJ_SCEMANTIC LDOBJ_NO_MATRIX - LDQuadObject() {} + LDQuad() {} // Split this quad into two triangles (note: heap-allocated) - List<LDTriangleObject*> splitToTriangles(); + List<LDTriangle*> splitToTriangles(); }; // ============================================================================= -// LDVertexObject +// LDVertex // // The vertex is an LDForce-specific extension which represents a single // vertex which can be used as a parameter to tools or to store coordinates // with. Vertices are a part authoring tool and they should not appear in // finished parts. // ============================================================================= -class LDVertexObject : public LDObject { +class LDVertex : public LDObject { public: LDOBJ (Vertex) LDOBJ_NAME (vertex) @@ -391,18 +403,18 @@ LDOBJ_NON_SCEMANTIC LDOBJ_NO_MATRIX - LDVertexObject() {} + LDVertex() {} vertex pos; }; // ============================================================================= -// LDOverlayObject +// LDOverlay // // Overlay image meta, stored in the header of parts so as to preserve overlay // information. // ============================================================================= -class LDOverlayObject : public LDObject { +class LDOverlay : public LDObject { LDOBJ (Overlay) LDOBJ_NAME (overlay) LDOBJ_VERTICES (0)
--- a/src/main.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/main.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -19,7 +19,7 @@ #include <QApplication> #include <QMessageBox> #include <QAbstractButton> -#include <qfile.h> +#include <QFile> #include <QTextStream> #include "gui.h" #include "file.h" @@ -28,6 +28,8 @@ #include "colors.h" #include "types.h" #include "primitives.h" +#include "gldraw.h" +#include "configDialog.h" List<LDFile*> g_loadedFiles; ForgeWindow* g_win = null; @@ -39,12 +41,57 @@ const vertex g_origin (0.0f, 0.0f, 0.0f); const matrix g_identity ({1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}); +cfg (Bool, firststart, true); + +// ============================================================================= +// ----------------------------------------------------------------------------- +int main (int argc, char* argv[]) { + QApplication app (argc, argv); + app.setOrganizationName (APPNAME); + app.setApplicationName (APPNAME); + + g_app = &app; + LDFile::setCurrent (null); + + // Load or create the configuration + if (!Config::load()) { + print ("Creating configuration file...\n"); + if (Config::save()) + print ("Configuration file successfully created.\n"); + else + print ("failed to create configuration file!\n"); + } + + LDPaths::initPaths(); + initColors(); + loadLogoedStuds(); + + ForgeWindow* win = new ForgeWindow; + newFile(); + win->show(); + + // If this is the first start, get the user to configuration. Especially point + // them to the profile tab, it's the most important form to fill in. + if (firststart) { + (new ConfigDialog (ConfigDialog::ProfileTab))->exec(); + firststart = false; + Config::save(); + } + + loadPrimitives(); + return app.exec(); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- void doPrint (File& f, initlist<StringFormatArg> args) { str msg = DoFormat (args); f.write (msg.toUtf8()); f.flush(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void doPrint (FILE* fp, initlist<StringFormatArg> args) { if (fp == stdout) doPrint (g_file_stdout, args); @@ -55,47 +102,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -int main (int argc, char* argv[]) { - QApplication app (argc, argv); - app.setOrganizationName (APPNAME); - app.setApplicationName (APPNAME); - - g_app = &app; - LDFile::setCurrent (null); - - // Load or create the configuration - if (!config::load()) { - print ("Creating configuration file...\n"); - if (config::save()) - print ("Configuration file successfully created.\n"); - else - print ("failed to create configuration file!\n"); - } - - LDPaths::initPaths(); - initColors(); - - ForgeWindow* win = new ForgeWindow; - - newFile(); - loadPrimitives(); - - win->show(); - return app.exec(); -} - -void doDevf (const char* func, const char* fmtstr, ...) { - va_list va; - - printf ("%s: ", func); - - va_start (va, fmtstr); - vprintf (fmtstr, va); - va_end (va); -} - +// ----------------------------------------------------------------------------- str versionString() { if (g_versionString.length() == 0) { #if VERSION_PATCH == 0 @@ -108,6 +115,8 @@ return g_versionString; } +// ============================================================================= +// ----------------------------------------------------------------------------- str versionMoniker() { #if BUILD_ID == BUILD_INTERNAL return "Internal"; @@ -122,10 +131,14 @@ #endif // BUILD_ID } +// ============================================================================= +// ----------------------------------------------------------------------------- str fullVersionString() { return fmt ("v%1 %2", versionString(), versionMoniker()); } +// ============================================================================= +// ----------------------------------------------------------------------------- static void bombBox (str msg) { msg.replace ("\n", "<br />"); @@ -141,6 +154,8 @@ box.exec(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void assertionFailure (const char* file, const ulong line, const char* funcname, const char* expr) { str errmsg = fmt ("File: %1\nLine: %2:\nFunction %3:\n\nAssertion `%4' failed", file, line, funcname, expr); @@ -162,6 +177,8 @@ #endif } +// ============================================================================= +// ----------------------------------------------------------------------------- void fatalError (const char* file, const ulong line, const char* funcname, str msg) { str errmsg = fmt ("Aborting over a call to fatal():\nFile: %1\nLine: %2\nFunction: %3\n\n%4", file, line, funcname, msg);
--- a/src/messagelog.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/messagelog.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,26 +1,26 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <QTimer> +#include <QDate> #include "messagelog.h" #include "gldraw.h" #include "gui.h" -#include <QTimer> -#include <QDate> static const unsigned int g_maxMessages = 5; static const int g_expiry = 5; @@ -46,6 +46,7 @@ // Check this line's expiry and update alpha accordingly. Returns true if the // line is to still stick around, false if it expired. 'changed' is updated to // whether the line has somehow changed since the last update. +// ----------------------------------------------------------------------------- bool MessageManager::Line::update (bool& changed) { changed = false; QDateTime now = QDateTime::currentDateTime(); @@ -67,8 +68,8 @@ } // ============================================================================= +// Add a line to the message manager. // ----------------------------------------------------------------------------- -// Add a line to the message manager. void MessageManager::addLine (str line) { // If there's too many entries, pop the excess out while (m_lines.size() >= g_maxMessages) @@ -82,17 +83,9 @@ } // ============================================================================= -// ----------------------------------------------------------------------------- -// Shortcut -MessageManager& MessageManager::operator<< (str line) { - addLine (line); - return *this; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- // Ticks the message manager. All lines are ticked and the renderer scene is // redrawn if something changed. +// ----------------------------------------------------------------------------- void MessageManager::tick() { if (m_lines.size() == 0) return; @@ -114,27 +107,18 @@ // ============================================================================= // ----------------------------------------------------------------------------- -// C++11-for loop support -MessageManager::c_it MessageManager::begin() const { - return m_lines.begin(); +const List<MessageManager::Line>& MessageManager::getLines() const { + return m_lines; } // ============================================================================= -// ----------------------------------------------------------------------------- -MessageManager::c_it MessageManager::end() const { - return m_lines.end(); -} - -// ============================================================================= -// ----------------------------------------------------------------------------- // log() interface - format the argument list and add the resulting string to // the main message manager. +// ----------------------------------------------------------------------------- void DoLog (std::initializer_list<StringFormatArg> args) { const str msg = DoFormat (args); g_win->addMessage (msg); // Also print it to stdout print ("%1\n", msg); -} - -#include "build/moc_messagelog.cpp" \ No newline at end of file +} \ No newline at end of file
--- a/src/messagelog.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/messagelog.h Sat Sep 07 13:23:09 2013 +0300 @@ -53,15 +53,9 @@ QDateTime expiry; }; - typedef List<Line>::it it; - typedef List<Line>::c_it c_it; - explicit MessageManager (QObject* parent = 0); void addLine (str line); - c_it begin() const; - c_it end() const; - - MessageManager& operator<< (str line); + const List<Line>& getLines() const; private: List<Line> m_lines;
--- a/src/misc.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/misc.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,24 +1,24 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <math.h> #include <locale.h> -#include <qcolor.h> +#include <QColor> #include "common.h" #include "misc.h" #include "gui.h" @@ -80,27 +80,26 @@ }; // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- // Grid stuff -cfg (int, grid, Grid::Medium); +cfg (Int, grid, Grid::Medium); -cfg (float, grid_coarse_x, 5.0f); -cfg (float, grid_coarse_y, 5.0f); -cfg (float, grid_coarse_z, 5.0f); -cfg (float, grid_coarse_angle, 45.0f); -cfg (float, grid_medium_x, 1.0f); -cfg (float, grid_medium_y, 1.0f); -cfg (float, grid_medium_z, 1.0f); -cfg (float, grid_medium_angle, 22.5f); -cfg (float, grid_fine_x, 0.1f); -cfg (float, grid_fine_y, 0.1f); -cfg (float, grid_fine_z, 0.1f); -cfg (float, grid_fine_angle, 7.5f); -cfg (int, edit_rotpoint, 0); -cfg (float, edit_rotpoint_x, 0.0f); // TODO: make a vertexconfig object and use it here -cfg (float, edit_rotpoint_y, 0.0f); -cfg (float, edit_rotpoint_z, 0.0f); +cfg (Float, grid_coarse_x, 5.0f); +cfg (Float, grid_coarse_y, 5.0f); +cfg (Float, grid_coarse_z, 5.0f); +cfg (Float, grid_coarse_angle, 45.0f); +cfg (Float, grid_medium_x, 1.0f); +cfg (Float, grid_medium_y, 1.0f); +cfg (Float, grid_medium_z, 1.0f); +cfg (Float, grid_medium_angle, 22.5f); +cfg (Float, grid_fine_x, 0.1f); +cfg (Float, grid_fine_y, 0.1f); +cfg (Float, grid_fine_z, 0.1f); +cfg (Float, grid_fine_angle, 7.5f); +cfg (Int, edit_rotpoint, 0); +cfg (Float, edit_rotpoint_x, 0.0f); // TODO: make a VertexConfig and use it here +cfg (Float, edit_rotpoint_y, 0.0f); +cfg (Float, edit_rotpoint_z, 0.0f); const gridinfo g_GridInfo[3] = { { "Coarse", { &grid_coarse_x, &grid_coarse_y, &grid_coarse_z, &grid_coarse_angle }}, @@ -110,6 +109,7 @@ // ============================================================================= // Snap the given coordinate value on the current grid's given axis. +// ----------------------------------------------------------------------------- double Grid::snap (double in, const Grid::Config axis) { const double gridval = currentGrid().confs[axis]->value; const long mult = abs (in / gridval); @@ -126,9 +126,9 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= // Float to string. Removes trailing zeroes and is locale-independant. +// TODO: Replace with QString::number() +// ----------------------------------------------------------------------------- str ftoa (double num) { // Disable the locale first so that the decimal point will not // turn into anything weird (like commas) @@ -150,8 +150,8 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// TODO: I guess Qt must have something like this stashed somewhere? +// ----------------------------------------------------------------------------- bool isNumber (const str& tok) { bool gotDot = false; @@ -180,8 +180,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void simplify (short& numer, short& denom) { bool repeat; @@ -205,6 +204,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- vertex rotPoint (const List<LDObject*>& objs) { LDBoundingBox box; @@ -229,6 +229,8 @@ return vertex(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void configRotationPoint() { QDialog* dlg = new QDialog; Ui::RotPointUI ui; @@ -265,6 +267,8 @@ edit_rotpoint_z = ui.customZ->value(); } +// ============================================================================= +// ----------------------------------------------------------------------------- str join (initlist<StringFormatArg> vals, str delim) { QStringList list; for (const StringFormatArg& arg : vals) @@ -273,6 +277,9 @@ return list.join (delim); } +// ============================================================================= +// TODO: I'm quite sure Qt has this covered as well. +// ----------------------------------------------------------------------------- double atof (str val) { // Disable the locale while parsing the line or atof's behavior changes // between locales (i.e. fails to read decimals properly). That is
--- a/src/misc.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/misc.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -47,10 +47,10 @@ // Grid stuff typedef struct { const char* const name; - floatconfig* const confs[4]; + FloatConfig* const confs[4]; } gridinfo; -extern_cfg (int, grid); +extern_cfg (Int, grid); static const short g_NumGrids = 3; extern const gridinfo g_GridInfo[3]; @@ -94,7 +94,7 @@ }; double snap (double value, const Grid::Config axis); -}; +} // ============================================================================= template<class T> void dataswap (T& a, T& b) {
--- a/src/primitives.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/primitives.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -32,20 +32,28 @@ static bool g_primListerMutex = false; List<Primitive> g_primitives; -static const str g_Other = QObject::tr ("Other"); +static const str g_Other = PrimitiveLister::tr ("Other"); + +static const str g_radialNameRoots[] = { + "edge", + "cyli", + "disc", + "ndis", + "ring", + "con" +}; static void populateCategories(); static void loadPrimitiveCatgories(); // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void loadPrimitives() { print ("Loading primitives...\n"); loadPrimitiveCatgories(); // Try to load prims.cfg - File conf (config::filepath ("prims.cfg"), File::Read); + File conf (Config::filepath ("prims.cfg"), File::Read); if (!conf) { // No prims.cfg, build it @@ -69,8 +77,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static void recursiveGetFilenames (QDir dir, List<str>& fnames) { QFileInfoList flist = dir.entryInfoList(); @@ -86,8 +93,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void PrimitiveLister::work() { g_activePrimLister = this; m_prims.clear(); @@ -118,13 +124,13 @@ info.title.remove (0, 1); // remove 0 info.title = info.title.simplified(); } - + m_prims << info; emit update (++i); } // Save to a config file - File conf (config::filepath ("prims.cfg"), File::Write); + File conf (Config::filepath ("prims.cfg"), File::Write); for (Primitive & info : m_prims) fprint (conf, "%1 %2\n", info.name, info.title); @@ -140,8 +146,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void PrimitiveLister::start() { if (g_activePrimLister) return; @@ -157,6 +162,8 @@ listerThread->start(); } +// ============================================================================= +// ----------------------------------------------------------------------------- static PrimitiveCategory* findCategory (str name) { for (PrimitiveCategory& cat : g_PrimitiveCategories) if (cat.name() == name) @@ -166,8 +173,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static void populateCategories() { for (PrimitiveCategory& cat : g_PrimitiveCategories) cat.prims.clear(); @@ -180,7 +186,7 @@ cat.setName (g_Other); unmatched = & (g_PrimitiveCategories << cat); } - + for (Primitive& prim : g_primitives) { bool matched = false; prim.cat = null; @@ -222,11 +228,10 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static void loadPrimitiveCatgories() { g_PrimitiveCategories.clear(); - File f (config::dirpath() + "primregexps.cfg", File::Read); + File f (Config::dirpath() + "primregexps.cfg", File::Read); if (!f) f.open (":/data/primitive-categories.cfg", File::Read); @@ -278,20 +283,19 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- bool primitiveLoaderBusy() { return g_primListerMutex; } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static double radialPoint (int i, int divs, double (*func) (double)) { return (*func) ((i * 2 * pi) / divs); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- List<LDObject*> makePrimitive (PrimitiveType type, int segs, int divs, int num) { List<LDObject*> objs; List<int> condLineSegs; @@ -307,7 +311,7 @@ vertex v0 (x0, 0.0f, z0), v1 (x1, 0.0f, z1); - LDLineObject* line = new LDLineObject; + LDLine* line = new LDLine; line->setVertex (0, v0); line->setVertex (1, v1); line->setColor (edgecolor); @@ -354,7 +358,7 @@ v2 (x2, y2, z2), v3 (x3, y3, z3); - LDQuadObject* quad = new LDQuadObject; + LDQuad* quad = new LDQuad; quad->setColor (maincolor); quad->setVertex (0, v0); quad->setVertex (1, v1); @@ -389,7 +393,7 @@ // Disc negatives need to go the other way around, otherwise // they'll end up upside-down. - LDTriangleObject* seg = new LDTriangleObject; + LDTriangle* seg = new LDTriangle; seg->setColor (maincolor); seg->setVertex (type == Disc ? 0 : 2, v0); seg->setVertex (1, v1); @@ -423,7 +427,7 @@ v0[Z] *= num; } - LDCondLineObject* line = new LDCondLineObject; + LDCndLine* line = new LDCndLine; line->setColor (edgecolor); line->setVertex (0, v0); line->setVertex (1, v1); @@ -436,8 +440,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- static str primitiveTypeName (PrimitiveType type) { // Not translated as primitives are in English. return type == Circle ? "Circle" : @@ -447,18 +450,8 @@ type == Ring ? "Ring" : "Cone"; } -static const str g_radialNameRoots[] = { - "edge", - "cyli", - "disc", - "ndis", - "ring", - "con" -}; - // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- str radialFileName (PrimitiveType type, int segs, int divs, int num) { short numer = segs, denom = divs; @@ -489,8 +482,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void generatePrimitive() { PrimitivePrompt* dlg = new PrimitivePrompt (g_win); @@ -532,20 +524,25 @@ LDFile* f = new LDFile; f->setName (QFileDialog::getSaveFileName (null, QObject::tr ("Save Primitive"), name)); - *f << new LDCommentObject (descr); - *f << new LDCommentObject (fmt ("Name: %1", name)); - *f << new LDCommentObject (fmt ("Author: LDForge")); - *f << new LDCommentObject (fmt ("!LDRAW_ORG Unofficial_%1Primitive", divs == hires ? "48_" : "")); - *f << new LDCommentObject (CALicense); - *f << new LDEmptyObject; - *f << new LDBFCObject (LDBFCObject::CertifyCCW); - *f << new LDEmptyObject; - *f << makePrimitive (type, segs, divs, num); + f->addObjects ({ + new LDComment (descr), + new LDComment (fmt ("Name: %1", name)), + new LDComment (fmt ("Author: LDForge")), + new LDComment (fmt ("!LDRAW_ORG Unofficial_%1Primitive", divs == hires ? "48_" : "")), + new LDComment (CALicense), + new LDEmpty, + new LDBFC (LDBFC::CertifyCCW), + new LDEmpty, + }); + + f->addObjects (makePrimitive (type, segs, divs, num)); g_win->save (f, false); delete f; } +// ============================================================================= +// ----------------------------------------------------------------------------- PrimitivePrompt::PrimitivePrompt (QWidget* parent, Qt::WindowFlags f) : QDialog (parent, f) { @@ -554,10 +551,14 @@ connect (ui->cb_hires, SIGNAL (toggled(bool)), this, SLOT (hiResToggled (bool))); } +// ============================================================================= +// ----------------------------------------------------------------------------- PrimitivePrompt::~PrimitivePrompt() { delete ui; } +// ============================================================================= +// ----------------------------------------------------------------------------- void PrimitivePrompt::hiResToggled (bool on) { ui->sb_segs->setMaximum (on ? hires : lores); @@ -565,6 +566,4 @@ // spinbox to 48. if (on && ui->sb_segs->value() == lores) ui->sb_segs->setValue (hires); -} - -#include "build/moc_primitives.cpp" \ No newline at end of file +} \ No newline at end of file
--- a/src/primitives.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/primitives.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */
--- a/src/types.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/types.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -5,7 +5,7 @@ * 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 3 of the License, or - * (at your option) any later version. + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,6 +27,8 @@ #include "ldtypes.h" #include "file.h" +// ============================================================================= +// ----------------------------------------------------------------------------- str DoFormat (List<StringFormatArg> args) { assert (args.size() >= 1); str text = args[0].value(); @@ -37,6 +39,8 @@ return text; } +// ============================================================================= +// ----------------------------------------------------------------------------- vertex::vertex (double x, double y, double z) { m_coords[X] = x; m_coords[Y] = y; @@ -44,12 +48,14 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void vertex::move (const vertex& other) { for (const Axis ax : g_Axes) m_coords[ax] += other[ax]; } // ============================================================================= +// ----------------------------------------------------------------------------- vertex vertex::midpoint (const vertex& other) { vertex mid; @@ -60,6 +66,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- str vertex::stringRep (bool mangled) const { str fmtstr = "%1 %2 %3"; if (mangled) @@ -69,6 +76,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void vertex::transform (matrix matr, vertex pos) { double x2 = (matr[0] * x()) + (matr[1] * y()) + (matr[2] * z()) + pos[X]; double y2 = (matr[3] * x()) + (matr[4] * y()) + (matr[5] * z()) + pos[Y]; @@ -79,14 +87,20 @@ z() = z2; } +// ============================================================================= +// ----------------------------------------------------------------------------- vertex vertex::operator-() const { return vertex (-m_coords[X], -m_coords[Y], -m_coords[Z]); } +// ============================================================================= +// ----------------------------------------------------------------------------- bool vertex::operator!= (const vertex& other) const { return !operator== (other); } +// ============================================================================= +// ----------------------------------------------------------------------------- double& vertex::operator[] (const Axis ax) { return coord ((ushort) ax); } @@ -103,12 +117,16 @@ return coord (ax); } +// ============================================================================= +// ----------------------------------------------------------------------------- bool vertex::operator== (const vertex& other) const { return coord (X) == other[X] && coord (Y) == other[Y] && coord (Z) == other[Z]; } +// ============================================================================= +// ----------------------------------------------------------------------------- vertex& vertex::operator/= (const double d) { for (const Axis ax : g_Axes) m_coords[ax] /= d; @@ -116,22 +134,30 @@ return *this; } +// ============================================================================= +// ----------------------------------------------------------------------------- vertex vertex::operator/ (const double d) const { vertex other (*this); return other /= d; } +// ============================================================================= +// ----------------------------------------------------------------------------- vertex& vertex::operator+= (const vertex& other) { move (other); return *this; } +// ============================================================================= +// ----------------------------------------------------------------------------- vertex vertex::operator+ (const vertex& other) const { vertex newvert (*this); newvert.move (other); return newvert; } +// ============================================================================= +// ----------------------------------------------------------------------------- int vertex::operator< (const vertex& other) const { if (operator== (other)) return false; @@ -152,21 +178,28 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- matrix::matrix (double vals[]) { for (short i = 0; i < 9; ++i) m_vals[i] = vals[i]; } +// ============================================================================= +// ----------------------------------------------------------------------------- matrix::matrix (double fillval) { for (short i = 0; i < 9; ++i) m_vals[i] = fillval; } +// ============================================================================= +// ----------------------------------------------------------------------------- matrix::matrix (initlist<double> vals) { assert (vals.size() == 9); memcpy (&m_vals[0], & (*vals.begin()), sizeof m_vals); } +// ============================================================================= +// ----------------------------------------------------------------------------- void matrix::puts() const { for (short i = 0; i < 3; ++i) { for (short j = 0; j < 3; ++j) @@ -177,6 +210,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- str matrix::stringRep() const { str val; @@ -191,11 +225,13 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- void matrix::zero() { - memset (&m_vals[0], 0, sizeof (double) * 9); + memset (&m_vals[0], 0, sizeof m_vals); } // ============================================================================= +// ----------------------------------------------------------------------------- matrix matrix::mult (matrix other) const { matrix val; val.zero(); @@ -203,18 +239,20 @@ for (short i = 0; i < 3; ++i) for (short j = 0; j < 3; ++j) for (short k = 0; k < 3; ++k) - val[ (i * 3) + j] += m_vals[ (i * 3) + k] * other[ (k * 3) + j]; - + val[ (i * 3) + j] += m_vals[(i * 3) + k] * other[(k * 3) + j]; + return val; } // ============================================================================= +// ----------------------------------------------------------------------------- matrix& matrix::operator= (matrix other) { - memcpy (&m_vals[0], &other.m_vals[0], sizeof (double) * 9); + memcpy (&m_vals[0], &other.m_vals[0], sizeof m_vals); return *this; } // ============================================================================= +// ----------------------------------------------------------------------------- double matrix::determinant() const { return (val (0) * val (4) * val (8)) + (val (1) * val (5) * val (6)) + @@ -225,6 +263,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- StringFormatArg::StringFormatArg (const str& v) { m_val = v; } @@ -261,15 +300,15 @@ m_val = v; } -StringFormatArg::StringFormatArg (const strconfig& v) { +StringFormatArg::StringFormatArg (const StringConfig& v) { m_val = v.value; } -StringFormatArg::StringFormatArg (const intconfig& v) { +StringFormatArg::StringFormatArg (const IntConfig& v) { m_val.number (v.value); } -StringFormatArg::StringFormatArg (const floatconfig& v) { +StringFormatArg::StringFormatArg (const FloatConfig& v) { m_val.number (v.value); } @@ -278,6 +317,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- File::File() { // Make a null file m_file = null; @@ -294,6 +334,8 @@ open (fp, rtype); } +// ============================================================================= +// ----------------------------------------------------------------------------- File::~File() { if (m_file) { m_file->close(); @@ -304,6 +346,8 @@ } } +// ============================================================================= +// ----------------------------------------------------------------------------- bool File::open (FILE* fp, OpenType rtype) { return open ("", rtype, fp); } @@ -337,6 +381,8 @@ return false; } +// ============================================================================= +// ----------------------------------------------------------------------------- File::iterator File::begin() { return iterator (this); } @@ -345,10 +391,14 @@ return m_endIterator; } +// ============================================================================= +// ----------------------------------------------------------------------------- void File::write (str msg) { m_file->write (msg.toUtf8(), msg.length()); } +// ============================================================================= +// ----------------------------------------------------------------------------- bool File::readLine (str& line) { if (!m_textstream || m_textstream->atEnd()) return false; @@ -357,6 +407,8 @@ return true; } +// ============================================================================= +// ----------------------------------------------------------------------------- bool File::atEnd() const { if (!m_textstream) fatal ("cannot use atEnd on a null file"); @@ -364,6 +416,8 @@ return m_textstream->atEnd(); } +// ============================================================================= +// ----------------------------------------------------------------------------- bool File::isNull() const { return m_file == null; } @@ -372,6 +426,8 @@ return isNull(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void File::close() { if (!m_file) return; @@ -385,76 +441,89 @@ } } +// ============================================================================= +// ----------------------------------------------------------------------------- bool File::flush() { return m_file->flush(); } +// ============================================================================= +// ----------------------------------------------------------------------------- File::operator bool() const { return !isNull(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void File::rewind() { m_file->seek (0); } +// ============================================================================= +// ----------------------------------------------------------------------------- File::iterator::iterator (File* f) : m_file (f) { operator++(); } +// ============================================================================= +// ----------------------------------------------------------------------------- void File::iterator::operator++() { m_gotdata = m_file->readLine (m_text); } +// ============================================================================= +// ----------------------------------------------------------------------------- str File::iterator::operator*() { return m_text; } +// ============================================================================= // The prime contestant for the weirdest operator== 2013 award? +// ----------------------------------------------------------------------------- bool File::iterator::operator== (File::iterator& other) { return (other.m_file == null && !m_gotdata); } +// ============================================================================= +// ----------------------------------------------------------------------------- bool File::iterator::operator!= (File::iterator& other) { return !operator== (other); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- LDBoundingBox::LDBoundingBox() { reset(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDBoundingBox::calculate() { reset(); if (!LDFile::current()) return; - for (LDObject* obj : LDFile::current()->objs()) + for (LDObject* obj : LDFile::current()->objects()) calcObject (obj); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDBoundingBox::calcObject (LDObject* obj) { switch (obj->getType()) { case LDObject::Line: case LDObject::Triangle: case LDObject::Quad: - case LDObject::CondLine: + case LDObject::CndLine: for (short i = 0; i < obj->vertices(); ++i) calcVertex (obj->getVertex (i)); break; case LDObject::Subfile: { - LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); - List<LDObject*> objs = ref->inlineContents (true, true); + LDSubfile* ref = static_cast<LDSubfile*> (obj); + List<LDObject*> objs = ref->inlineContents (LDSubfile::DeepCacheInline); for (LDObject* obj : objs) { calcObject (obj); @@ -468,19 +537,22 @@ } } +// ============================================================================= +// ----------------------------------------------------------------------------- LDBoundingBox& LDBoundingBox::operator<< (const vertex& v) { calcVertex (v); return *this; } +// ============================================================================= +// ----------------------------------------------------------------------------- LDBoundingBox& LDBoundingBox::operator<< (LDObject* obj) { calcObject (obj); return *this; } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDBoundingBox::calcVertex (const vertex& v) { for (const Axis ax : g_Axes) { if (v[ax] < m_v0[ax]) @@ -494,8 +566,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- void LDBoundingBox::reset() { m_v0[X] = m_v0[Y] = m_v0[Z] = 0x7FFFFFFF; m_v1[X] = m_v1[Y] = m_v1[Z] = 0xFFFFFFFF; @@ -504,8 +575,7 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= +// ----------------------------------------------------------------------------- double LDBoundingBox::size() const { double xscale = (m_v0[X] - m_v1[X]); double yscale = (m_v0[Y] - m_v1[Y]); @@ -525,6 +595,7 @@ } // ============================================================================= +// ----------------------------------------------------------------------------- vertex LDBoundingBox::center() const { return vertex ( (m_v0[X] + m_v1[X]) / 2,
--- a/src/types.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/types.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -30,9 +30,9 @@ typedef QString str; template<class T> class ConstListReverser; template<class T> using c_rev = ConstListReverser<T>; -class strconfig; -class intconfig; -class floatconfig; +class StringConfig; +class IntConfig; +class FloatConfig; class QFile; class QTextStream; @@ -279,6 +279,11 @@ std::deque<T> m_vect; }; +template<class T> static inline T& operator>> (const T& a, List<T>& b) { + b.insert (0, a); + return b; +} + // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= @@ -370,9 +375,9 @@ StringFormatArg (const vertex& v); StringFormatArg (const matrix& v); StringFormatArg (const char* v); - StringFormatArg (const strconfig& v); - StringFormatArg (const intconfig& v); - StringFormatArg (const floatconfig& v); + StringFormatArg (const StringConfig& v); + StringFormatArg (const IntConfig& v); + StringFormatArg (const FloatConfig& v); StringFormatArg (const void* v); template<class T> StringFormatArg (const List<T>& v) { @@ -509,6 +514,6 @@ extern const vertex g_origin; // Vertex at (0, 0, 0) extern const matrix g_identity; // Identity matrix -static const double pi = 3.14159265358979323846f; +static const double pi = 3.14159265358979323846; #endif // TYPES_H \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ui/addhistoryline.ui Sat Sep 07 13:23:09 2013 +0300 @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AddHistoryLine</class> + <widget class="QDialog" name="AddHistoryLine"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>410</width> + <height>120</height> + </rect> + </property> + <property name="windowTitle"> + <string>Add History Line</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Date:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QDateEdit" name="m_date"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Username:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="m_username"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Comment:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="m_comment"/> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>AddHistoryLine</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>AddHistoryLine</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- a/src/ui/config.ui Fri Aug 16 11:05:21 2013 +0300 +++ b/src/ui/config.ui Sat Sep 07 13:23:09 2013 +0300 @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>513</width> - <height>377</height> + <width>561</width> + <height>351</height> </rect> </property> <property name="windowTitle"> @@ -24,7 +24,7 @@ <enum>QTabWidget::North</enum> </property> <property name="currentIndex"> - <number>5</number> + <number>0</number> </property> <property name="elideMode"> <enum>Qt::ElideNone</enum> @@ -40,7 +40,7 @@ </property> <widget class="QWidget" name="tab"> <attribute name="title"> - <string>General</string> + <string>Interface</string> </attribute> <layout class="QVBoxLayout" name="verticalLayout_2"> <item> @@ -190,40 +190,157 @@ </layout> </item> <item> - <widget class="QCheckBox" name="colorizeObjects"> - <property name="whatsThis"> - <string>Makes colored objects (non-16 and 24) appear colored in the list view. A red triangle will, for instance, have its entry written in red text. This can be useful to locate colored objects.</string> - </property> - <property name="text"> - <string>Colorize objects in list view</string> - </property> - </widget> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_11"> + <item> + <widget class="QCheckBox" name="blackEdges"> + <property name="whatsThis"> + <string>Makes all edgelines appear black. If this is not set, edge lines take their color as defined in LDConfig.ldr.</string> + </property> + <property name="text"> + <string>Black edges</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="colorBFC"> + <property name="whatsThis"> + <string>Polygons' front sides become green and back sides red.</string> + </property> + <property name="text"> + <string>Red/green BFC view (incomplete)</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="colorizeObjects"> + <property name="whatsThis"> + <string>Makes colored objects (non-16 and 24) appear colored in the list view. A red triangle will, for instance, have its entry written in red text. This can be useful to locate colored objects.</string> + </property> + <property name="text"> + <string>Colorize objects in list view</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="implicitFiles"> + <property name="text"> + <string>List implicitly loaded files</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_12"> + <item> + <widget class="QCheckBox" name="m_logostuds"> + <property name="text"> + <string>Use logoed studs</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_6"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> </item> + </layout> + </widget> + <widget class="QWidget" name="tab_7"> + <attribute name="title"> + <string>Profile</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_10"> <item> - <widget class="QCheckBox" name="colorBFC"> - <property name="whatsThis"> - <string>Polygons' front sides become green and back sides red.</string> - </property> - <property name="text"> - <string>Red/green BFC view (incomplete)</string> + <widget class="QGroupBox" name="groupBox_4"> + <property name="title"> + <string>Profile</string> </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="blackEdges"> - <property name="whatsThis"> - <string>Makes all edgelines appear black. If this is not set, edge lines take their color as defined in LDConfig.ldr.</string> - </property> - <property name="text"> - <string>Black edges</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="implicitFiles"> - <property name="text"> - <string>List implicitly loaded files</string> - </property> + <layout class="QVBoxLayout" name="verticalLayout_8"> + <item> + <layout class="QFormLayout" name="formLayout_3"> + <item row="2" column="0"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>Username:</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Name:</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>License:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="m_profileName"/> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="m_profileUsername"/> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="m_profileLicense"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>CA - redistributable</string> + </property> + </item> + <item> + <property name="text"> + <string>NonCA - not redistributable</string> + </property> + </item> + <item> + <property name="text"> + <string>None</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_7"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> </widget> </item> </layout> @@ -574,7 +691,7 @@ <enum>Qt::Horizontal</enum> </property> <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> </property> </widget> </item> @@ -583,38 +700,5 @@ <resources> <include location="../../ldforge.qrc"/> </resources> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>ConfigUI</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>ConfigUI</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> + <connections/> </ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ui/extprogpath.ui Sat Sep 07 13:23:09 2013 +0300 @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ExtProgPath</class> + <widget class="QDialog" name="ExtProgPath"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>444</width> + <height>89</height> + </rect> + </property> + <property name="windowTitle"> + <string>Program path required</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="m_label"> + <property name="text"> + <string>Please input a path for <PROGRAM>:</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLineEdit" name="m_path"/> + </item> + <item> + <widget class="QPushButton" name="m_findPath"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ExtProgPath</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ExtProgPath</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- a/src/ui/ldforge.ui Fri Aug 16 11:05:21 2013 +0300 +++ b/src/ui/ldforge.ui Sat Sep 07 13:23:09 2013 +0300 @@ -70,7 +70,7 @@ <x>0</x> <y>0</y> <width>900</width> - <height>26</height> + <height>22</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -159,6 +159,8 @@ <addaction name="actionModeDraw"/> <addaction name="separator"/> <addaction name="actionSetDrawDepth"/> + <addaction name="separator"/> + <addaction name="actionJumpTo"/> </widget> <widget class="QMenu" name="menuTools"> <property name="title"> @@ -173,6 +175,8 @@ <addaction name="actionInlineDeep"/> <addaction name="actionMakePrimitive"/> <addaction name="separator"/> + <addaction name="actionAddHistoryLine"/> + <addaction name="separator"/> <addaction name="actionSplitQuads"/> <addaction name="actionEditRaw"/> <addaction name="actionBorders"/> @@ -1264,6 +1268,16 @@ <string>Download From...</string> </property> </action> + <action name="actionAddHistoryLine"> + <property name="text"> + <string>Add History Line</string> + </property> + </action> + <action name="actionJumpTo"> + <property name="text"> + <string>Go to Line...</string> + </property> + </action> </widget> <resources> <include location="../../ldforge.qrc"/>
--- a/src/widgets.cpp Fri Aug 16 11:05:21 2013 +0300 +++ b/src/widgets.cpp Sat Sep 07 13:23:09 2013 +0300 @@ -1,21 +1,25 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +// I still find the radio group useful... find a way to use this in Designer. +// I probably need to look into how to make Designer plugins. +// TODO: try make this usable in Designer + #include <QBoxLayout> #include <QRadioButton> #include <QButtonGroup> @@ -24,19 +28,27 @@ #include "widgets.h" -RadioBox::RadioBox (const QString& title, QWidget* parent) : QGroupBox (title, parent) { +// ============================================================================= +// ----------------------------------------------------------------------------- +RadioGroup::RadioGroup (const QString& title, QWidget* parent) : QGroupBox (title, parent) { init (Qt::Vertical); } +// ============================================================================= +// ----------------------------------------------------------------------------- QBoxLayout::Direction makeDirection (Qt::Orientation orient, bool invert = false) { return (orient == (invert ? Qt::Vertical : Qt::Horizontal)) ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom; } -bool RadioBox::isChecked (int n) const { +// ============================================================================= +// ----------------------------------------------------------------------------- +bool RadioGroup::isChecked (int n) const { return m_buttonGroup->checkedId() == n; } -void RadioBox::init (Qt::Orientation orient) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void RadioGroup::init (Qt::Orientation orient) { m_vert = orient == Qt::Vertical; m_buttonGroup = new QButtonGroup; @@ -53,7 +65,9 @@ connect (m_buttonGroup, SIGNAL (buttonReleased (int)), this, SLOT (slot_buttonReleased (int))); } -RadioBox::RadioBox (const QString& title, initlist<char const*> entries, int const defaultId, +// ============================================================================= +// ----------------------------------------------------------------------------- +RadioGroup::RadioGroup (const QString& title, initlist<char const*> entries, int const defaultId, const Qt::Orientation orient, QWidget* parent) : QGroupBox (title, parent), m_defId (defaultId) { init (orient); @@ -63,7 +77,9 @@ addButton (entry); } -void RadioBox::rowBreak() { +// ============================================================================= +// ----------------------------------------------------------------------------- +void RadioGroup::rowBreak() { QBoxLayout* newLayout = new QBoxLayout (m_vert ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight); m_currentLayout = newLayout; m_layouts << newLayout; @@ -71,12 +87,16 @@ m_coreLayout->addLayout (newLayout); } -void RadioBox::addButton (const char* entry) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void RadioGroup::addButton (const char* entry) { QRadioButton* button = new QRadioButton (entry); addButton (button); } -void RadioBox::addButton (QRadioButton* button) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void RadioGroup::addButton (QRadioButton* button) { bool const selectThis = (m_curId == m_defId); m_objects << button; @@ -87,39 +107,55 @@ button->setChecked (true); } -RadioBox& RadioBox::operator<< (QRadioButton* button) { +// ============================================================================= +// ----------------------------------------------------------------------------- +RadioGroup& RadioGroup::operator<< (QRadioButton* button) { addButton (button); return *this; } -RadioBox& RadioBox::operator<< (const char* entry) { +// ============================================================================= +// ----------------------------------------------------------------------------- +RadioGroup& RadioGroup::operator<< (const char* entry) { addButton (entry); return *this; } -void RadioBox::setCurrentRow (uint row) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void RadioGroup::setCurrentRow (uint row) { m_currentLayout = m_layouts[row]; } -int RadioBox::value() const { +// ============================================================================= +// ----------------------------------------------------------------------------- +int RadioGroup::value() const { return m_buttonGroup->checkedId(); } -void RadioBox::setValue (int val) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void RadioGroup::setValue (int val) { m_buttonGroup->button (val)->setChecked (true); } -QRadioButton* RadioBox::operator[] (uint n) const { +// ============================================================================= +// ----------------------------------------------------------------------------- +QRadioButton* RadioGroup::operator[] (uint n) const { return m_objects[n]; } -void RadioBox::slot_buttonPressed (int btn) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void RadioGroup::slot_buttonPressed (int btn) { emit buttonPressed (btn); m_oldId = m_buttonGroup->checkedId(); } -void RadioBox::slot_buttonReleased (int btn) { +// ============================================================================= +// ----------------------------------------------------------------------------- +void RadioGroup::slot_buttonReleased (int btn) { emit buttonReleased (btn); int newid = m_buttonGroup->checkedId(); @@ -127,12 +163,14 @@ emit valueChanged (newid); } -RadioBox::it RadioBox::begin() { +// ============================================================================= +// ----------------------------------------------------------------------------- +RadioGroup::it RadioGroup::begin() { return m_objects.begin(); } -RadioBox::it RadioBox::end() { +// ============================================================================= +// ----------------------------------------------------------------------------- +RadioGroup::it RadioGroup::end() { return m_objects.end(); -} - -#include "build/moc_widgets.cpp" \ No newline at end of file +} \ No newline at end of file
--- a/src/widgets.h Fri Aug 16 11:05:21 2013 +0300 +++ b/src/widgets.h Sat Sep 07 13:23:09 2013 +0300 @@ -1,17 +1,17 @@ /* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 Santeri Piippo - * + * * 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 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -25,26 +25,27 @@ #include "common.h" #include "types.h" +class QIcon; class QCheckBox; class QButtonGroup; class QBoxLayout; class QRadioButton; // ============================================================================= -// RadioBox +// RadioGroup // // Convenience widget - is a groupbox of radio buttons. // ============================================================================= -class RadioBox : public QGroupBox { +class RadioGroup : public QGroupBox { Q_OBJECT public: typedef List<QRadioButton*>::it it; - explicit RadioBox() { init (Qt::Vertical); } - explicit RadioBox (QWidget* parent = null) : QGroupBox (parent) { init (Qt::Vertical); } - explicit RadioBox (const QString& title, QWidget* parent = null); - explicit RadioBox (const QString& title, initlist<char const*> entries, int const defaultId, + explicit RadioGroup() { init (Qt::Vertical); } + explicit RadioGroup (QWidget* parent = null) : QGroupBox (parent) { init (Qt::Vertical); } + explicit RadioGroup (const QString& title, QWidget* parent = null); + explicit RadioGroup (const QString& title, initlist<char const*> entries, int const defaultId, const Qt::Orientation orient = Qt::Vertical, QWidget* parent = null); void addButton (const char* entry); @@ -59,8 +60,8 @@ int value () const; QRadioButton* operator[] (uint n) const; - RadioBox& operator<< (QRadioButton* button); - RadioBox& operator<< (const char* entry); + RadioGroup& operator<< (QRadioButton* button); + RadioGroup& operator<< (const char* entry); signals: void buttonPressed (int btn); @@ -76,7 +77,7 @@ int m_curId, m_defId, m_oldId; QButtonGroup* m_buttonGroup; - Q_DISABLE_COPY (RadioBox) + Q_DISABLE_COPY (RadioGroup) private slots: void slot_buttonPressed (int btn);