Tue, 16 Jul 2013 02:47:11 +0300
change camera to top if switching to draw mode in free camera
/* * 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> #include <QFileDialog> #include <QColorDialog> #include <QBoxLayout> #include <QKeyEvent> #include <QGroupBox> #include <QDoubleSpinBox> #include <QLineEdit> #include <QCheckBox> #include "common.h" #include "configDialog.h" #include "file.h" #include "config.h" #include "misc.h" #include "colors.h" #include "colorSelectDialog.h" #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 (int, gui_toolbar_iconsize); extern_cfg (str, gui_colortoolbar); extern_cfg (bool, edit_schemanticinline); extern_cfg (bool, gl_blackedges); #define act(N) extern_cfg (keyseq, key_##N); #include "actions.h" #define INIT_CHECKBOX(BOX, CFG) \ BOX->setCheckState (CFG ? Qt::Checked : Qt::Unchecked); #define APPLY_CHECKBOX(BTN, CFG) \ CFG = BTN->checkState() == Qt::Checked; // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= ConfigDialog::ConfigDialog (ForgeWindow* parent) : QDialog (parent) { ui = new Ui_ConfigUI; ui->setupUi( this ); initMainTab (); initShortcutsTab (); initQuickColorTab (); initGridTab (); initExtProgTab (); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= ConfigDialog::~ConfigDialog() { delete ui; } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ConfigDialog::initMainTab () { // Init color stuff setButtonBackground (ui->backgroundColorButton, gl_bgcolor); connect (ui->backgroundColorButton, SIGNAL (clicked ()), this, SLOT (slot_setGLBackground ())); setButtonBackground (ui->mainColorButton, gl_maincolor.value); connect (ui->mainColorButton, SIGNAL (clicked ()), this, SLOT (slot_setGLForeground ())); ui->mainColorAlpha->setValue( gl_maincolor_alpha * 10.0f ); // Sliders ui->lineThickness->setValue( gl_linethickness ); ui->iconSize->setValue(( gui_toolbar_iconsize - 12 ) / 4 ); // Checkboxes ui->colorizeObjects->setChecked( lv_colorize ); ui->colorBFC->setChecked( gl_colorbfc ); ui->blackEdges->setChecked (gl_blackedges); ui->scemanticInlining->setChecked (edit_schemanticinline); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ConfigDialog::initShortcutsTab () { ulong i = 0; #define act(N) addShortcut (key_##N, ACTION(N), i); #include "actions.h" ui->shortcutsList->setSortingEnabled( true ); ui->shortcutsList->sortItems(); 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() )); } void ConfigDialog::addShortcut (keyseqconfig& cfg, QAction* act, ulong& i) { ShortcutListItem* item = new ShortcutListItem; item->setIcon (act->icon()); item->setKeyConfig (&cfg); item->setAction (act); setShortcutText (item); // If the action doesn't have a valid icon, use an empty one // so that the list is kept aligned. if (act->icon().isNull()) item->setIcon (getIcon ("empty")); ui->shortcutsList->insertItem (i++, item); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ConfigDialog::initQuickColorTab() { quickColorMeta = parseQuickColorMeta(); 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() { QGridLayout* gridlayout = new QGridLayout; QLabel* xlabel = new QLabel( "X" ), *ylabel = new QLabel( "Y" ), *zlabel = new QLabel( "Z" ), *anglabel = new QLabel( "Angle" ); short i = 1; for( QLabel* label : initlist<QLabel*> ({ xlabel, ylabel, zlabel, anglabel })) { label->setAlignment( Qt::AlignCenter ); gridlayout->addWidget( label, 0, i++ ); } for( int i = 0; i < g_NumGrids; ++i ) { // Icon lb_gridIcons[i] = new QLabel; lb_gridIcons[i]->setPixmap( getIcon( fmt( "grid-%1", str( g_GridInfo[i].name ).toLower() ))); // Text label lb_gridLabels[i] = new QLabel( fmt( "%1:", g_GridInfo[i].name )); QHBoxLayout* labellayout = new QHBoxLayout; labellayout->addWidget( lb_gridIcons[i] ); labellayout->addWidget( lb_gridLabels[i] ); gridlayout->addLayout( labellayout, i + 1, 0 ); // Add the widgets for( int j = 0; j < 4; ++j ) { dsb_gridData[i][j] = new QDoubleSpinBox; dsb_gridData[i][j]->setValue( g_GridInfo[i].confs[j]->value ); gridlayout->addWidget( dsb_gridData[i][j], i + 1, j + 1 ); } } ui->grids->setLayout( gridlayout ); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= 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 ); static const struct extProgInfo { const str name, iconname; strconfig* const path; mutable QLineEdit* input; mutable QPushButton* setPathButton; #ifndef _WIN32 boolconfig* const wine; mutable QCheckBox* wineBox; #endif // _WIN32 } g_extProgInfo[] = { #ifndef _WIN32 # define EXTPROG( NAME, LOWNAME ) { #NAME, #LOWNAME, &prog_##LOWNAME, null, null, &prog_##LOWNAME##_wine, null }, #else # define EXTPROG( NAME, LOWNAME ) { #NAME, #LOWNAME, &prog_##LOWNAME, null, null }, #endif EXTPROG( Ytruder, ytruder ) EXTPROG( Rectifier, rectifier ) EXTPROG( Intersector, intersector ) EXTPROG( Isecalc, isecalc ) EXTPROG( Coverer, coverer ) EXTPROG( Edger2, edger2 ) #undef EXTPROG }; void ConfigDialog::initExtProgTab() { QGridLayout* pathsLayout = new QGridLayout; ulong row = 0; for( const extProgInfo & info : g_extProgInfo ) { QLabel* icon = new QLabel, *progLabel = new QLabel( info.name ); QLineEdit* input = new QLineEdit; QPushButton* setPathButton = new QPushButton; icon->setPixmap( getIcon( info.iconname )); input->setText( info.path->value ); setPathButton->setIcon( getIcon( "folder" )); info.input = input; info.setPathButton = setPathButton; connect( setPathButton, SIGNAL( clicked() ), this, SLOT( slot_setExtProgPath() )); pathsLayout->addWidget( icon, row, 0 ); pathsLayout->addWidget( progLabel, row, 1 ); pathsLayout->addWidget( input, row, 2 ); pathsLayout->addWidget( setPathButton, row, 3 ); #ifndef _WIN32 QCheckBox* wineBox = new QCheckBox( "Wine" ); wineBox->setChecked( *info.wine ); info.wineBox = wineBox; pathsLayout->addWidget( wineBox, row, 4 ); #endif ++row; } ui->extProgs->setLayout( pathsLayout ); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ConfigDialog::updateQuickColorList( quickColor* sel ) { for( QListWidgetItem* item : quickColorItems ) delete item; quickColorItems.clear(); // Init table items for( quickColor& entry : quickColorMeta ) { QListWidgetItem* item = new QListWidgetItem; if( entry.isSeparator ) { item->setText( "--------" ); item->setIcon( getIcon( "empty" )); } else { LDColor* col = entry.col; if( col == null ) { item->setText( "[[unknown color]]" ); item->setIcon( getIcon( "error" )); } else { item->setText( col->name ); item->setIcon( makeColorIcon( col, 16 )); } } ui->quickColorList->addItem( item ); quickColorItems << item; if( sel && &entry == sel ) { ui->quickColorList->setCurrentItem( item ); ui->quickColorList->scrollToItem( item ); } } } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ConfigDialog::slot_setColor() { quickColor* entry = null; QListWidgetItem* item = null; const bool isNew = static_cast<QPushButton*>( sender() ) == ui->quickColor_add; if( isNew == false ) { item = getSelectedQuickColor(); if( !item ) return; ulong i = getItemRow( item, quickColorItems ); entry = &quickColorMeta[i]; if( entry->isSeparator == true ) return; // don't color separators } short defval = entry ? entry->col->index : -1; short val; if( ColorSelector::getColor( val, defval, this ) == false ) return; if( entry ) entry->col = getColor( val ); else { quickColor entry = {getColor( val ), null, false}; item = getSelectedQuickColor(); ulong idx; if( item ) idx = getItemRow( item, quickColorItems ) + 1; else idx = quickColorItems.size(); quickColorMeta.insert( idx, entry ); entry = quickColorMeta[idx]; } updateQuickColorList( entry ); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ConfigDialog::slot_delColor() { if( ui->quickColorList->selectedItems().size() == 0 ) return; QListWidgetItem* item = ui->quickColorList->selectedItems()[0]; quickColorMeta.erase( getItemRow( item, quickColorItems )); updateQuickColorList(); } // ============================================================================= void ConfigDialog::slot_moveColor() { const bool up = ( static_cast<QPushButton*>( sender() ) == ui->quickColor_moveUp ); if( ui->quickColorList->selectedItems().size() == 0 ) return; QListWidgetItem* item = ui->quickColorList->selectedItems()[0]; int idx = getItemRow( item, quickColorItems ); int dest = up ? ( idx - 1 ) : ( idx + 1 ); if( dest < 0 || ( ulong ) dest >= quickColorItems.size() ) return; // destination out of bounds quickColor tmp = quickColorMeta[dest]; quickColorMeta[dest] = quickColorMeta[idx]; quickColorMeta[idx] = tmp; updateQuickColorList( &quickColorMeta[dest] ); } // ============================================================================= void ConfigDialog::slot_addColorSeparator() { quickColorMeta << quickColor({ null, null, true }); updateQuickColorList( &quickColorMeta[quickColorMeta.size() - 1] ); } // ============================================================================= void ConfigDialog::slot_clearColors() { quickColorMeta.clear(); updateQuickColorList(); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ConfigDialog::pickColor( strconfig& conf, QPushButton* button ) { QColor col = QColorDialog::getColor( QColor( conf )); if( col.isValid() ) { uchar r = col.red(), g = col.green(), b = col.blue(); conf.value.sprintf( "#%.2X%.2X%.2X", r, g, b ); setButtonBackground( button, conf.value ); } } void ConfigDialog::slot_setGLBackground() { pickColor( gl_bgcolor, ui->backgroundColorButton ); } void ConfigDialog::slot_setGLForeground() { pickColor( gl_maincolor, ui->mainColorButton ); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ConfigDialog::setButtonBackground( QPushButton* button, str value ) { button->setIcon( getIcon( "colorselect" )); button->setAutoFillBackground( true ); button->setStyleSheet( fmt( "background-color: %1", value )); } // ============================================================================= int ConfigDialog::getItemRow( QListWidgetItem* item, vector<QListWidgetItem*>& haystack ) { int i = 0; for( QListWidgetItem * it : haystack ) { if( it == item ) return i; ++i; } return -1; } // ============================================================================= QListWidgetItem* ConfigDialog::getSelectedQuickColor() { if( ui->quickColorList->selectedItems().size() == 0 ) return null; return ui->quickColorList->selectedItems()[0]; } // ============================================================================= QList<ShortcutListItem*> ConfigDialog::getShortcutSelection() { QList<ShortcutListItem*> out; for( QListWidgetItem * entry : ui->shortcutsList->selectedItems() ) out << static_cast<ShortcutListItem*>( entry ); return out; } // ============================================================================= void ConfigDialog::slot_setShortcut() { QList<ShortcutListItem*> sel = getShortcutSelection(); if( sel.size() < 1 ) return; ShortcutListItem* item = sel[0]; if (KeySequenceDialog::staticDialog (item->keyConfig(), this)) setShortcutText (item); } // ============================================================================= void ConfigDialog::slot_resetShortcut() { QList<ShortcutListItem*> sel = getShortcutSelection(); for (ShortcutListItem* item : sel) { item->keyConfig()->reset(); setShortcutText (item); } } // ============================================================================= void ConfigDialog::slot_clearShortcut() { QList<ShortcutListItem*> sel = getShortcutSelection(); for (ShortcutListItem* item : sel) { item->keyConfig()->value = QKeySequence(); setShortcutText (item); } } // ============================================================================= void ConfigDialog::slot_setExtProgPath() { const extProgInfo* info = null; for (const extProgInfo& it : g_extProgInfo) { if (it.setPathButton == sender()) { info = ⁢ break; } } 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, filter ); if( fpath.length() == 0 ) return; info->input->setText( fpath ); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ConfigDialog::setShortcutText( ShortcutListItem* item ) { QAction* act = item->action(); str label = act->iconText(); str keybind = item->keyConfig()->value.toString(); item->setText (fmt ("%1 (%2)", label, keybind)); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= str ConfigDialog::makeColorToolBarString() { str val; for( quickColor entry : quickColorMeta ) { if( val.length() > 0 ) val += ':'; if( entry.isSeparator ) val += '|'; else val += fmt( "%1", entry.col->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_toolbar_iconsize = ( dlg.getUI()->iconSize->value() * 4 ) + 12; // Manage the quick color toolbar g_win->setQuickColorMeta( dlg.quickColorMeta ); gui_colortoolbar = dlg.makeColorToolBarString(); // 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 } // Save the config config::save(); // Reload all subfiles as the ldraw path potentially changed. reloadAllSubfiles(); g_win->R()->setBackground(); g_win->fullRefresh(); g_win->updateToolBars(); } } // ========================================================================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ========================================================================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ========================================================================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ========================================================================================================================= KeySequenceDialog::KeySequenceDialog( QKeySequence seq, QWidget* parent, Qt::WindowFlags f ) : QDialog( parent, f ), seq( seq ) { lb_output = new QLabel; IMPLEMENT_DIALOG_BUTTONS setWhatsThis( "Into this dialog you can input a key sequence for use as a " "shortcut in LDForge. Use OK to confirm the new shortcut and Cancel to " "dismiss." ); QVBoxLayout* layout = new QVBoxLayout; layout->addWidget( lb_output ); layout->addWidget( bbx_buttons ); setLayout( layout ); updateOutput(); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= bool KeySequenceDialog::staticDialog (keyseqconfig* cfg, QWidget* parent) { KeySequenceDialog dlg (cfg->value, parent); if (dlg.exec() == false) return false; cfg->value = dlg.seq; return true; } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void KeySequenceDialog::updateOutput() { str shortcut = seq.toString(); if( seq == QKeySequence() ) shortcut = "<empty>"; str text = fmt( "<center><b>%1</b></center>", shortcut ); lb_output->setText( text ); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void KeySequenceDialog::keyPressEvent( QKeyEvent* ev ) { seq = ev->key() + ev->modifiers(); updateOutput(); }