2017-02-12 13:21:08 +01:00
/*
KLayout Layout Viewer
2017-02-12 15:28:14 +01:00
Copyright ( C ) 2006 - 2017 Matthias Koefferlein
2017-02-12 13:21:08 +01:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This 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 , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# include "layStream.h"
# include "layTechSetupDialog.h"
# include "layTechnology.h"
# include "tlExceptions.h"
# include "layFileDialog.h"
# include "layTipDialog.h"
# include "layMainWindow.h"
# include "layApplication.h"
# include "layMacroEditorTree.h"
# include "layMacro.h"
2017-04-15 01:03:24 +02:00
# include "layMacroController.h"
# include "layTechnologyController.h"
2017-02-12 13:21:08 +01:00
# include "tlAssert.h"
# include "tlStream.h"
# include "dbStream.h"
# include <QInputDialog>
# include <QMessageBox>
# include <QHeaderView>
# include <QFileDialog>
# include <QScrollArea>
# include <stdio.h>
# include <fstream>
namespace lay
{
// ----------------------------------------------------------------
// TechBaseEditorPage implementation
TechBaseEditorPage : : TechBaseEditorPage ( QWidget * parent )
: TechnologyComponentEditor ( parent )
{
Ui : : TechBaseEditorPage : : setupUi ( this ) ;
connect ( browse_pb , SIGNAL ( clicked ( ) ) , this , SLOT ( browse_clicked ( ) ) ) ;
connect ( browse_lyp_pb , SIGNAL ( clicked ( ) ) , this , SLOT ( browse_lyp_clicked ( ) ) ) ;
}
void
TechBaseEditorPage : : setup ( )
{
name_le - > setText ( tl : : to_qstring ( tech ( ) - > name ( ) ) ) ;
desc_le - > setText ( tl : : to_qstring ( tech ( ) - > description ( ) ) ) ;
dbu_le - > setText ( tl : : to_qstring ( tl : : to_string ( tech ( ) - > dbu ( ) ) ) ) ;
desc_le - > setEnabled ( ! tech ( ) - > name ( ) . empty ( ) ) ;
base_path_le - > setText ( tl : : to_qstring ( tech ( ) - > explicit_base_path ( ) ) ) ;
# if QT_VERSION >= 0x040700
base_path_le - > setPlaceholderText ( tl : : to_qstring ( tech ( ) - > default_base_path ( ) ) ) ;
# endif
const std : : string & lyp = tech ( ) - > layer_properties_file ( ) ;
lyp_grp - > setChecked ( ! lyp . empty ( ) ) ;
lyp_le - > setText ( tl : : to_qstring ( lyp ) ) ;
add_other_layers_cbx - > setChecked ( tech ( ) - > add_other_layers ( ) ) ;
}
void
TechBaseEditorPage : : commit ( )
{
tech ( ) - > set_description ( tl : : to_string ( desc_le - > text ( ) ) ) ;
tech ( ) - > set_explicit_base_path ( tl : : to_string ( base_path_le - > text ( ) ) ) ;
double d = 0.001 ;
tl : : from_string ( tl : : to_string ( dbu_le - > text ( ) ) , d ) ;
tech ( ) - > set_dbu ( d ) ;
if ( ! lyp_grp - > isChecked ( ) ) {
tech ( ) - > set_layer_properties_file ( std : : string ( ) ) ;
tech ( ) - > set_add_other_layers ( true ) ;
} else {
tech ( ) - > set_layer_properties_file ( tl : : to_string ( lyp_le - > text ( ) ) ) ;
tech ( ) - > set_add_other_layers ( add_other_layers_cbx - > isChecked ( ) ) ;
}
}
void
TechBaseEditorPage : : browse_clicked ( )
{
QString p = QFileDialog : : getExistingDirectory ( this , QObject : : tr ( " Choose Base Path " ) ,
base_path_le - > text ( ) ) ;
if ( ! p . isNull ( ) ) {
base_path_le - > setText ( p ) ;
}
}
void
TechBaseEditorPage : : browse_lyp_clicked ( )
{
lay : : FileDialog open_dialog ( this ,
tl : : to_string ( QObject : : tr ( " Browse Layer Properties File " ) ) ,
tl : : to_string ( QObject : : tr ( " Layer properties files (*.lyp);;Text files (*.txt);;All files (*) " ) ) ) ;
std : : string lyp = tech ( ) - > base_path ( ) ;
if ( open_dialog . get_open ( lyp ) ) {
lyp_le - > setText ( tl : : to_qstring ( tech ( ) - > correct_path ( lyp ) ) ) ;
}
}
// ----------------------------------------------------------------
// TechLoadOptionsEditorPage implementation
TechLoadOptionsEditorPage : : TechLoadOptionsEditorPage ( QWidget * parent )
: TechnologyComponentEditor ( parent )
{
Ui : : TechLoadOptionsEditorPage : : setupUi ( this ) ;
while ( options_tab - > count ( ) > 0 ) {
options_tab - > removeTab ( 0 ) ;
}
bool any_option = false ;
for ( tl : : Registrar < db : : StreamFormatDeclaration > : : iterator fmt = tl : : Registrar < db : : StreamFormatDeclaration > : : begin ( ) ; fmt ! = tl : : Registrar < db : : StreamFormatDeclaration > : : end ( ) ; + + fmt ) {
StreamReaderOptionsPage * page = 0 ;
// obtain the config page from the plugin which we identify by format name
const StreamReaderPluginDeclaration * decl = StreamReaderPluginDeclaration : : plugin_for_format ( fmt - > format_name ( ) ) ;
if ( decl ) {
QScrollArea * page_host = new QScrollArea ( options_tab ) ;
page_host - > setFrameStyle ( QFrame : : NoFrame ) ;
page_host - > setWidgetResizable ( true ) ;
page = decl - > format_specific_options_page ( options_tab ) ;
if ( page ) {
page_host - > setWidget ( page ) ;
options_tab - > addTab ( page_host , tl : : to_qstring ( fmt - > format_desc ( ) ) ) ;
any_option = true ;
} else {
delete page_host ;
}
}
#if 0
// Add dummy pages for empty options
if ( ! page ) {
QLabel * empty = new QLabel ( options_tab ) ;
empty - > setAlignment ( Qt : : AlignCenter ) ;
empty - > setText ( QObject : : tr ( " No specific options available for this format " ) ) ;
options_tab - > addTab ( empty , tl : : to_qstring ( fmt - > format_desc ( ) ) ) ;
}
# endif
if ( page ) {
m_pages . push_back ( std : : make_pair ( page , fmt - > format_name ( ) ) ) ;
}
}
if ( ! any_option ) {
options_tab - > hide ( ) ;
}
}
void
TechLoadOptionsEditorPage : : setup ( )
{
for ( std : : vector < std : : pair < StreamReaderOptionsPage * , std : : string > > : : iterator page = m_pages . begin ( ) ; page ! = m_pages . end ( ) ; + + page ) {
if ( page - > first ) {
page - > first - > setup ( tech ( ) - > load_layout_options ( ) . get_options ( page - > second ) , tech ( ) ) ;
}
}
}
void
TechLoadOptionsEditorPage : : commit ( )
{
// create the particular options for all formats
db : : LoadLayoutOptions options = tech ( ) - > load_layout_options ( ) ;
for ( std : : vector < std : : pair < StreamReaderOptionsPage * , std : : string > > : : iterator page = m_pages . begin ( ) ; page ! = m_pages . end ( ) ; + + page ) {
if ( page - > first ) {
db : : FormatSpecificReaderOptions * specific_options = options . get_options ( page - > second ) ;
if ( ! specific_options ) {
specific_options = StreamReaderPluginDeclaration : : plugin_for_format ( page - > second ) - > create_specific_options ( ) ;
options . set_options ( specific_options ) ;
}
page - > first - > commit ( specific_options , tech ( ) ) ;
}
}
tech ( ) - > set_load_layout_options ( options ) ;
}
// ----------------------------------------------------------------
// TechSaveOptionsEditorPage implementation
TechSaveOptionsEditorPage : : TechSaveOptionsEditorPage ( QWidget * parent )
: TechnologyComponentEditor ( parent )
{
Ui : : TechSaveOptionsEditorPage : : setupUi ( this ) ;
while ( options_tab - > count ( ) > 0 ) {
options_tab - > removeTab ( 0 ) ;
}
bool any_option = false ;
for ( tl : : Registrar < db : : StreamFormatDeclaration > : : iterator fmt = tl : : Registrar < db : : StreamFormatDeclaration > : : begin ( ) ; fmt ! = tl : : Registrar < db : : StreamFormatDeclaration > : : end ( ) ; + + fmt ) {
StreamWriterOptionsPage * page = 0 ;
// obtain the config page from the plugin which we identify by format name
const StreamWriterPluginDeclaration * decl = StreamWriterPluginDeclaration : : plugin_for_format ( fmt - > format_name ( ) ) ;
if ( decl ) {
QScrollArea * page_host = new QScrollArea ( options_tab ) ;
page_host - > setFrameStyle ( QFrame : : NoFrame ) ;
page_host - > setWidgetResizable ( true ) ;
page = decl - > format_specific_options_page ( options_tab ) ;
if ( page ) {
page_host - > setWidget ( page ) ;
options_tab - > addTab ( page_host , tl : : to_qstring ( fmt - > format_desc ( ) ) ) ;
any_option = true ;
} else {
delete page_host ;
}
}
#if 0
// Add dummy pages for empty options
if ( ! page ) {
QLabel * empty = new QLabel ( options_tab ) ;
empty - > setAlignment ( Qt : : AlignCenter ) ;
empty - > setText ( QObject : : tr ( " No specific options available for this format " ) ) ;
options_tab - > addTab ( empty , tl : : to_qstring ( fmt - > format_desc ( ) ) ) ;
}
# endif
if ( page ) {
m_pages . push_back ( std : : make_pair ( page , fmt - > format_name ( ) ) ) ;
}
}
if ( ! any_option ) {
options_tab - > hide ( ) ;
}
}
void
TechSaveOptionsEditorPage : : setup ( )
{
for ( std : : vector < std : : pair < StreamWriterOptionsPage * , std : : string > > : : iterator page = m_pages . begin ( ) ; page ! = m_pages . end ( ) ; + + page ) {
if ( page - > first ) {
page - > first - > setup ( tech ( ) - > save_layout_options ( ) . get_options ( page - > second ) , tech ( ) ) ;
}
}
}
void
TechSaveOptionsEditorPage : : commit ( )
{
// create the particular options for all formats
db : : SaveLayoutOptions options = tech ( ) - > save_layout_options ( ) ;
for ( std : : vector < std : : pair < StreamWriterOptionsPage * , std : : string > > : : iterator page = m_pages . begin ( ) ; page ! = m_pages . end ( ) ; + + page ) {
if ( page - > first ) {
db : : FormatSpecificWriterOptions * specific_options = options . get_options ( page - > second ) ;
if ( ! specific_options ) {
specific_options = StreamWriterPluginDeclaration : : plugin_for_format ( page - > second ) - > create_specific_options ( ) ;
options . set_options ( specific_options ) ;
}
page - > first - > commit ( specific_options , tech ( ) , false /*gzip*/ ) ;
}
}
tech ( ) - > set_save_layout_options ( options ) ;
}
// ----------------------------------------------------------------
// TechMacrosPage implementation
TechMacrosPage : : TechMacrosPage ( QWidget * parent , const std : : string & cat , const std : : string & cat_desc )
: TechnologyComponentEditor ( parent ) , m_cat ( cat ) , m_cat_desc ( cat_desc )
{
Ui : : TechMacrosPage : : setupUi ( this ) ;
m_original_labels . push_back ( std : : make_pair ( title_label , title_label - > text ( ) ) ) ;
m_original_labels . push_back ( std : : make_pair ( note_label , note_label - > text ( ) ) ) ;
m_original_labels . push_back ( std : : make_pair ( empty_label1 , empty_label1 - > text ( ) ) ) ;
m_original_labels . push_back ( std : : make_pair ( empty_label2 , empty_label2 - > text ( ) ) ) ;
m_original_labels . push_back ( std : : make_pair ( empty_label3 , empty_label3 - > text ( ) ) ) ;
folder_tree - > header ( ) - > hide ( ) ;
connect ( folder_tree , SIGNAL ( clicked ( const QModelIndex & ) ) , this , SLOT ( macro_selected ( const QModelIndex & ) ) ) ;
QFont f = macro_text - > font ( ) ;
f . setFixedPitch ( true ) ;
f . setFamily ( tl : : to_qstring ( " Monospace " ) ) ;
macro_text - > setFont ( f ) ;
connect ( create_folder_button , SIGNAL ( clicked ( ) ) , this , SLOT ( create_folder_clicked ( ) ) ) ;
}
TechMacrosPage : : ~ TechMacrosPage ( )
{
// do this before the collection gets deleted.
delete folder_tree - > model ( ) ;
}
void
TechMacrosPage : : setup ( )
{
title_label - > show ( ) ;
macro_frame - > show ( ) ;
note_label - > show ( ) ;
empty_label1 - > hide ( ) ;
empty_label3 - > hide ( ) ;
empty_label2_frame - > hide ( ) ;
QDir base_dir ( tl : : to_qstring ( tech ( ) - > base_path ( ) ) ) ;
QDir macro_dir ( base_dir . filePath ( tl : : to_qstring ( m_cat ) ) ) ;
QString cp = macro_dir . canonicalPath ( ) ;
// if a macro collection already exists, show a readonly copy of this one
const lay : : MacroCollection * original = 0 ;
const lay : : MacroCollection * root = & lay : : MacroCollection : : root ( ) ;
for ( lay : : MacroCollection : : const_child_iterator m = root - > begin_children ( ) ; m ! = root - > end_children ( ) & & ! original ; + + m ) {
if ( m - > second - > virtual_mode ( ) = = lay : : MacroCollection : : TechFolder & & m - > second - > category ( ) = = m_cat & & QDir ( tl : : to_qstring ( m - > second - > path ( ) ) ) . canonicalPath ( ) = = cp ) {
original = m - > second ;
}
}
const lay : : MacroCollection * alt = 0 ;
for ( lay : : MacroCollection : : const_child_iterator m = root - > begin_children ( ) ; m ! = root - > end_children ( ) & & ! alt ; + + m ) {
if ( m - > second - > virtual_mode ( ) ! = lay : : MacroCollection : : TechFolder & & QDir ( tl : : to_qstring ( m - > second - > path ( ) ) ) . canonicalPath ( ) = = cp ) {
alt = m - > second ;
}
}
// adjust labels
for ( std : : vector < std : : pair < QLabel * , QString > > : : const_iterator ol = m_original_labels . begin ( ) ; ol ! = m_original_labels . end ( ) ; + + ol ) {
QString l = ol - > second ;
l . replace ( QString : : fromUtf8 ( " %CAT% " ) , tl : : to_qstring ( m_cat ) ) ;
l . replace ( QString : : fromUtf8 ( " %CAT_DESC% " ) , tl : : to_qstring ( m_cat_desc ) ) ;
l . replace ( QString : : fromUtf8 ( " %BASE_PATH% " ) , tl : : to_qstring ( tech ( ) - > base_path ( ) ) ) ;
if ( alt ) {
l . replace ( QString : : fromUtf8 ( " %ALT_DESC% " ) , tl : : to_qstring ( alt - > description ( ) ) ) ;
} else {
l . replace ( QString : : fromUtf8 ( " %ALT_DESC% " ) , QString : : fromUtf8 ( " *unknown* " ) ) ;
}
ol - > first - > setText ( l ) ;
}
if ( tech ( ) - > base_path ( ) . empty ( ) ) {
// no base path set
title_label - > hide ( ) ;
empty_label1 - > show ( ) ;
macro_frame - > hide ( ) ;
note_label - > hide ( ) ;
} else {
if ( ! macro_dir . exists ( ) ) {
// macro folder not found
title_label - > hide ( ) ;
empty_label2_frame - > show ( ) ;
macro_frame - > hide ( ) ;
note_label - > hide ( ) ;
} else {
// valid macros to show
std : : string mp = tl : : to_string ( macro_dir . path ( ) ) ;
if ( mp_collection . get ( ) & & m_current_path = = mp ) {
// .. nothing to do ..
} else {
if ( ! original & & alt ) {
// this can happen, if the macro collection is already there in a different context.
// Show a message indicating that
title_label - > hide ( ) ;
empty_label3 - > show ( ) ;
macro_frame - > hide ( ) ;
note_label - > hide ( ) ;
} else {
std : : string desc ;
if ( original ) {
desc = original - > description ( ) ;
} else {
desc = tl : : to_string ( QObject : : tr ( " Technology " ) ) + " - " + tech ( ) - > name ( ) ;
}
lay : : MacroCollection * mc = new lay : : MacroCollection ( ) ;
mp_collection . reset ( mc ) ;
mc - > add_folder ( desc , mp , m_cat , true ) ;
m_current_path = mp ;
delete folder_tree - > model ( ) ;
folder_tree - > setModel ( new lay : : MacroTreeModel ( this , mc , m_cat ) ) ;
folder_tree - > expandAll ( ) ;
macro_text - > hide ( ) ;
}
}
}
}
}
void
TechMacrosPage : : create_folder_clicked ( )
{
BEGIN_PROTECTED
QString macro_dir = QDir ( tl : : to_qstring ( tech ( ) - > base_path ( ) ) ) . absoluteFilePath ( tl : : to_qstring ( m_cat ) ) ;
if ( ! QDir : : root ( ) . mkpath ( macro_dir ) ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " Failed to create folder: " ) ) + tl : : to_string ( macro_dir ) ) ;
}
setup ( ) ;
END_PROTECTED
}
void
TechMacrosPage : : macro_selected ( const QModelIndex & index )
{
const lay : : Macro * m = 0 ;
lay : : MacroTreeModel * model = dynamic_cast < lay : : MacroTreeModel * > ( folder_tree - > model ( ) ) ;
if ( model & & model - > is_valid_pointer ( index . internalPointer ( ) ) ) {
m = dynamic_cast < lay : : Macro * > ( ( QObject * ) index . internalPointer ( ) ) ;
}
if ( ! m ) {
macro_text - > hide ( ) ;
} else {
macro_text - > show ( ) ;
macro_text - > setPlainText ( tl : : to_qstring ( m - > text ( ) ) ) ;
}
}
void
TechMacrosPage : : commit ( )
{
// .. noting yet ..
}
// ----------------------------------------------------------------
// TechSetupDialog implementation
static bool s_first_show = true ;
TechSetupDialog : : TechSetupDialog ( QWidget * parent )
: QDialog ( parent ) , mp_current_tech ( 0 ) , mp_current_editor ( 0 ) , mp_current_tech_component ( 0 )
{
setObjectName ( QString : : fromUtf8 ( " tech_setup_dialog " ) ) ;
Ui : : TechSetupDialog : : setupUi ( this ) ;
QAction * add_action = new QAction ( QObject : : tr ( " Add Technology " ) , this ) ;
connect ( add_action , SIGNAL ( triggered ( ) ) , this , SLOT ( add_clicked ( ) ) ) ;
QAction * delete_action = new QAction ( QObject : : tr ( " Delete Technology " ) , this ) ;
connect ( delete_action , SIGNAL ( triggered ( ) ) , this , SLOT ( delete_clicked ( ) ) ) ;
QAction * rename_action = new QAction ( QObject : : tr ( " Rename Technology " ) , this ) ;
connect ( rename_action , SIGNAL ( triggered ( ) ) , this , SLOT ( rename_clicked ( ) ) ) ;
QAction * import_action = new QAction ( QObject : : tr ( " Import Technology " ) , this ) ;
connect ( import_action , SIGNAL ( triggered ( ) ) , this , SLOT ( import_clicked ( ) ) ) ;
QAction * export_action = new QAction ( QObject : : tr ( " Export Technology " ) , this ) ;
connect ( export_action , SIGNAL ( triggered ( ) ) , this , SLOT ( export_clicked ( ) ) ) ;
2017-04-15 01:03:24 +02:00
QAction * refresh_action = new QAction ( QObject : : tr ( " Refresh " ) , this ) ;
connect ( refresh_action , SIGNAL ( triggered ( ) ) , this , SLOT ( refresh_clicked ( ) ) ) ;
QAction * separator ;
2017-02-12 13:21:08 +01:00
tech_tree - > addAction ( add_action ) ;
tech_tree - > addAction ( delete_action ) ;
tech_tree - > addAction ( rename_action ) ;
2017-04-15 01:03:24 +02:00
separator = new QAction ( this ) ;
2017-02-12 13:21:08 +01:00
separator - > setSeparator ( true ) ;
tech_tree - > addAction ( separator ) ;
tech_tree - > addAction ( import_action ) ;
tech_tree - > addAction ( export_action ) ;
2017-04-15 01:03:24 +02:00
separator = new QAction ( this ) ;
separator - > setSeparator ( true ) ;
tech_tree - > addAction ( separator ) ;
tech_tree - > addAction ( refresh_action ) ;
2017-02-12 13:21:08 +01:00
tech_tree - > header ( ) - > hide ( ) ;
connect ( tech_tree , SIGNAL ( currentItemChanged ( QTreeWidgetItem * , QTreeWidgetItem * ) ) , this , SLOT ( current_tech_changed ( QTreeWidgetItem * , QTreeWidgetItem * ) ) ) ;
connect ( add_pb , SIGNAL ( clicked ( ) ) , this , SLOT ( add_clicked ( ) ) ) ;
connect ( delete_pb , SIGNAL ( clicked ( ) ) , this , SLOT ( delete_clicked ( ) ) ) ;
connect ( rename_pb , SIGNAL ( clicked ( ) ) , this , SLOT ( rename_clicked ( ) ) ) ;
if ( s_first_show ) {
TipDialog td ( this ,
tl : : to_string ( QObject : : tr ( " <html><body>To get started with the technology manager, read the documentation provided: <a href= \" int:/about/technology_manager.xml \" >About Technology Management</a>.</body></html> " ) ) ,
" tech-manager-basic-tips " ) ;
td . exec_dialog ( ) ;
s_first_show = false ;
}
}
TechSetupDialog : : ~ TechSetupDialog ( )
{
clear_components ( ) ;
}
void
TechSetupDialog : : clear_components ( )
{
for ( std : : map < std : : string , lay : : TechnologyComponent * > : : iterator tc = m_technology_components . begin ( ) ; tc ! = m_technology_components . end ( ) ; + + tc ) {
delete tc - > second ;
}
m_technology_components . clear ( ) ;
for ( std : : map < std : : string , lay : : TechnologyComponentEditor * > : : iterator tce = m_component_editors . begin ( ) ; tce ! = m_component_editors . end ( ) ; + + tce ) {
tc_stack - > removeWidget ( tce - > second ) ;
delete tce - > second ;
}
m_component_editors . clear ( ) ;
mp_current_editor = 0 ;
mp_current_tech_component = 0 ;
}
2017-04-15 01:03:24 +02:00
void
TechSetupDialog : : refresh_clicked ( )
{
BEGIN_PROTECTED
2017-04-15 17:51:04 +02:00
lay : : TechnologyController : : instance ( ) - > refresh ( m_technologies ) ;
2017-04-15 01:03:24 +02:00
update ( ) ;
END_PROTECTED
}
void
TechSetupDialog : : update ( )
2017-02-12 13:21:08 +01:00
{
update_tech_tree ( ) ;
tech_tree - > setCurrentItem ( tech_tree - > topLevelItem ( 0 ) ) ;
update_tech ( selected_tech ( ) ) ;
2017-04-15 01:03:24 +02:00
}
int
2017-04-15 17:51:04 +02:00
TechSetupDialog : : exec ( lay : : Technologies & technologies )
2017-04-15 01:03:24 +02:00
{
2017-04-15 17:51:04 +02:00
m_technologies = technologies ;
2017-04-15 01:03:24 +02:00
update ( ) ;
2017-02-12 13:21:08 +01:00
tc_stack - > setMinimumSize ( tc_stack - > sizeHint ( ) ) ;
int ret = QDialog : : exec ( ) ;
if ( ret ) {
2017-04-15 17:51:04 +02:00
technologies = m_technologies ;
2017-02-12 13:21:08 +01:00
}
// clean up
update_tech ( 0 ) ;
m_technologies = lay : : Technologies ( ) ;
update_tech_tree ( ) ;
return ret ;
}
void
TechSetupDialog : : add_clicked ( )
{
BEGIN_PROTECTED
commit_tech_component ( ) ;
lay : : Technology * t = selected_tech ( ) ;
if ( ! t ) {
t = m_technologies . technology_by_name ( std : : string ( ) ) ;
tl_assert ( t ! = 0 ) ;
}
std : : string d = t - > name ( ) ;
if ( ! d . empty ( ) & & ! t - > description ( ) . empty ( ) ) {
d + = " - " ;
}
d + = t - > description ( ) ;
bool ok = false ;
QString tn = QInputDialog : : getText ( this , QObject : : tr ( " Add Technology " ) ,
tl : : to_qstring ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " This will create a new technology based on the selected technology '%s'. \n Choose a name for the new technology. " ) ) , d ) ) ,
QLineEdit : : Normal ,
QString ( ) ,
& ok ) ;
if ( ok & & ! tn . isEmpty ( ) ) {
tn = tn . simplified ( ) ;
if ( m_technologies . has_technology ( tl : : to_string ( tn ) ) ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " A technology with this name already exists " ) ) ) ;
}
2017-04-15 01:03:24 +02:00
QDir root = QDir ( tl : : to_qstring ( lay : : TechnologyController : : instance ( ) - > default_root ( ) ) ) ;
QDir tech_dir ( root . filePath ( tn ) ) ;
if ( tech_dir . exists ( ) ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " A target folder with path '%1' already exists " ) . arg ( tech_dir . path ( ) ) ) ) ;
}
2017-02-12 13:21:08 +01:00
lay : : Technology * nt = new lay : : Technology ( * t ) ;
2017-04-15 01:03:24 +02:00
nt - > set_tech_file_path ( tl : : to_string ( tech_dir . absoluteFilePath ( tn + QString : : fromUtf8 ( " .lyt " ) ) ) ) ;
nt - > set_persisted ( false ) ;
2017-02-12 13:21:08 +01:00
nt - > set_name ( tl : : to_string ( tn ) ) ;
nt - > set_description ( std : : string ( ) ) ;
m_technologies . add ( nt ) ;
update_tech_tree ( ) ;
select_tech ( * m_technologies . technology_by_name ( tl : : to_string ( tn ) ) ) ;
}
END_PROTECTED
}
void
TechSetupDialog : : delete_clicked ( )
{
BEGIN_PROTECTED
lay : : Technology * t = selected_tech ( ) ;
if ( ! t ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " No technology selected " ) ) ) ;
}
if ( t - > name ( ) . empty ( ) ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " The default technology cannot be deleted " ) ) ) ;
}
2017-04-15 01:03:24 +02:00
if ( t - > is_readonly ( ) ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " This technology is read-only and cannot be deleted " ) ) ) ;
2017-02-12 13:21:08 +01:00
}
if ( QMessageBox : : question ( this , QObject : : tr ( " Deleting Technology " ) ,
QObject : : tr ( " Are you sure to delete this technology? \n This operation cannot be undone, except by cancelling the technology manager. " ) ,
QMessageBox : : No | QMessageBox : : Yes ) = = QMessageBox : : Yes ) {
for ( lay : : Technologies : : const_iterator i = m_technologies . begin ( ) ; i ! = m_technologies . end ( ) ; + + i ) {
if ( i - > name ( ) = = t - > name ( ) ) {
m_technologies . remove ( i - > name ( ) ) ;
2017-04-15 01:03:24 +02:00
2017-02-12 13:21:08 +01:00
update_tech_tree ( ) ;
select_tech ( * m_technologies . technology_by_name ( std : : string ( ) ) ) ;
break ;
}
}
}
END_PROTECTED
}
void
TechSetupDialog : : rename_clicked ( )
{
BEGIN_PROTECTED
commit_tech_component ( ) ;
lay : : Technology * t = selected_tech ( ) ;
if ( ! t ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " No technology selected " ) ) ) ;
}
if ( t - > name ( ) . empty ( ) ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " The default technology cannot be renamed " ) ) ) ;
}
2017-04-15 01:03:24 +02:00
if ( t - > is_readonly ( ) ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " This technology is read-only and cannot be renamed " ) ) ) ;
2017-02-12 13:21:08 +01:00
}
bool ok = false ;
QString tn = QInputDialog : : getText ( this , QObject : : tr ( " Rename Technology " ) ,
QObject : : tr ( " Choose a name for the technology " ) ,
QLineEdit : : Normal ,
tl : : to_qstring ( t - > name ( ) ) ,
& ok ) ;
if ( ok & & ! tn . isEmpty ( ) ) {
tn = tn . simplified ( ) ;
if ( m_technologies . has_technology ( tl : : to_string ( tn ) ) ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " A technology with this name already exists " ) ) ) ;
}
2017-04-15 01:03:24 +02:00
if ( t - > name ( ) ! = tl : : to_string ( tn ) ) {
2017-02-12 13:21:08 +01:00
2017-04-15 01:03:24 +02:00
t - > set_name ( tl : : to_string ( tn ) ) ;
if ( ! t - > is_persisted ( ) & & ! t - > tech_file_path ( ) . empty ( ) ) {
TipDialog td ( this ,
tl : : to_string ( QObject : : tr ( " <html><body>Renaming of a technology will neither rename the technology file or the folder the file is stored in.<br/>The file or folder needs to be renamed manually.</body></html> " ) ) ,
" tech-manager-rename-tip " ) ;
td . exec_dialog ( ) ;
}
update_tech_tree ( ) ;
select_tech ( * t ) ;
}
2017-02-12 13:21:08 +01:00
}
END_PROTECTED
}
void
TechSetupDialog : : import_clicked ( )
{
BEGIN_PROTECTED
lay : : FileDialog open_dialog ( this , tl : : to_string ( QObject : : tr ( " Import Technology " ) ) , tl : : to_string ( QObject : : tr ( " KLayout technology files (*.lyt);;All files (*) " ) ) ) ;
std : : string fn ;
if ( open_dialog . get_open ( fn ) ) {
lay : : Technology t ;
t . load ( fn ) ;
if ( m_technologies . has_technology ( t . name ( ) ) ) {
* m_technologies . technology_by_name ( t . name ( ) ) = t ;
} else {
m_technologies . add ( new lay : : Technology ( t ) ) ;
}
update_tech_tree ( ) ;
select_tech ( * m_technologies . technology_by_name ( t . name ( ) ) ) ;
}
END_PROTECTED
}
void
TechSetupDialog : : export_clicked ( )
{
BEGIN_PROTECTED
lay : : Technology * t = selected_tech ( ) ;
if ( ! t ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " No technology selected " ) ) ) ;
}
lay : : FileDialog save_dialog ( this , tl : : to_string ( QObject : : tr ( " Export Technology " ) ) , tl : : to_string ( QObject : : tr ( " KLayout technology files (*.lyt);;All files (*) " ) ) ) ;
std : : string fn ;
if ( save_dialog . get_save ( fn ) ) {
t - > save ( fn ) ;
}
END_PROTECTED
}
void
TechSetupDialog : : update_tech_tree ( )
{
tech_tree - > clear ( ) ;
std : : map < std : : string , const lay : : Technology * > tech_by_name ;
for ( lay : : Technologies : : const_iterator t = m_technologies . begin ( ) ; t ! = m_technologies . end ( ) ; + + t ) {
tech_by_name . insert ( std : : make_pair ( t - > name ( ) , & * t ) ) ;
}
for ( std : : map < std : : string , const lay : : Technology * > : : const_iterator t = tech_by_name . begin ( ) ; t ! = tech_by_name . end ( ) ; + + t ) {
QFont f ( tech_tree - > font ( ) ) ;
2017-04-15 01:03:24 +02:00
f . setItalic ( t - > second - > is_readonly ( ) ) ;
2017-02-12 13:21:08 +01:00
std : : string d ;
d + = t - > first ;
if ( ! d . empty ( ) & & ! t - > second - > description ( ) . empty ( ) ) {
d + = " - " ;
}
d + = t - > second - > description ( ) ;
QTreeWidgetItem * ti = new QTreeWidgetItem ( tech_tree ) ;
ti - > setData ( 0 , Qt : : DisplayRole , QVariant ( tl : : to_qstring ( d ) ) ) ;
ti - > setData ( 0 , Qt : : UserRole , QVariant ( tl : : to_qstring ( t - > first ) ) ) ;
ti - > setData ( 0 , Qt : : FontRole , QVariant ( f ) ) ;
2017-04-15 01:03:24 +02:00
if ( ! t - > second - > tech_file_path ( ) . empty ( ) ) {
ti - > setData ( 0 , Qt : : ToolTipRole , QVariant ( tl : : to_qstring ( t - > second - > tech_file_path ( ) ) ) ) ;
}
2017-02-12 13:21:08 +01:00
std : : vector < std : : string > tc_names = t - > second - > component_names ( ) ;
std : : map < std : : string , const lay : : TechnologyComponent * > tc_by_name ;
for ( std : : vector < std : : string > : : const_iterator n = tc_names . begin ( ) ; n ! = tc_names . end ( ) ; + + n ) {
tc_by_name . insert ( std : : make_pair ( * n , t - > second - > component_by_name ( * n ) ) ) ;
}
QTreeWidgetItem * tci = new QTreeWidgetItem ( ti ) ;
tci - > setData ( 0 , Qt : : DisplayRole , QVariant ( QObject : : tr ( " General " ) ) ) ;
tci - > setData ( 0 , Qt : : UserRole + 1 , QVariant ( tl : : to_qstring ( " _general " ) ) ) ;
tci - > setData ( 0 , Qt : : FontRole , QVariant ( f ) ) ;
tci = new QTreeWidgetItem ( ti ) ;
tci - > setData ( 0 , Qt : : DisplayRole , QVariant ( QObject : : tr ( " Reader Options " ) ) ) ;
tci - > setData ( 0 , Qt : : UserRole + 1 , QVariant ( tl : : to_qstring ( " _load_options " ) ) ) ;
tci - > setData ( 0 , Qt : : FontRole , QVariant ( f ) ) ;
tci = new QTreeWidgetItem ( ti ) ;
tci - > setData ( 0 , Qt : : DisplayRole , QVariant ( QObject : : tr ( " Writer Options " ) ) ) ;
tci - > setData ( 0 , Qt : : UserRole + 1 , QVariant ( tl : : to_qstring ( " _save_options " ) ) ) ;
tci - > setData ( 0 , Qt : : FontRole , QVariant ( f ) ) ;
2017-04-15 01:03:24 +02:00
if ( lay : : MacroController : : instance ( ) ) {
const std : : vector < std : : pair < std : : string , std : : string > > & mc = lay : : MacroController : : instance ( ) - > macro_categories ( ) ;
for ( std : : vector < std : : pair < std : : string , std : : string > > : : const_iterator c = mc . begin ( ) ; c ! = mc . end ( ) ; + + c ) {
tci = new QTreeWidgetItem ( ti ) ;
tci - > setData ( 0 , Qt : : DisplayRole , QVariant ( tl : : to_qstring ( c - > second ) ) ) ;
tci - > setData ( 0 , Qt : : UserRole + 1 , QVariant ( tl : : to_qstring ( std : : string ( " _macros_ " ) + c - > first ) ) ) ;
tci - > setData ( 0 , Qt : : FontRole , QVariant ( f ) ) ;
}
2017-02-12 13:21:08 +01:00
}
for ( std : : map < std : : string , const lay : : TechnologyComponent * > : : const_iterator c = tc_by_name . begin ( ) ; c ! = tc_by_name . end ( ) ; + + c ) {
tci = new QTreeWidgetItem ( ti ) ;
tci - > setData ( 0 , Qt : : DisplayRole , QVariant ( tl : : to_qstring ( c - > second - > description ( ) ) ) ) ;
tci - > setData ( 0 , Qt : : UserRole + 1 , QVariant ( tl : : to_qstring ( c - > first ) ) ) ;
tci - > setData ( 0 , Qt : : FontRole , QVariant ( f ) ) ;
}
}
}
void
TechSetupDialog : : update_tech ( lay : : Technology * t )
{
if ( t = = mp_current_tech ) {
return ;
}
mp_current_tech = t ;
clear_components ( ) ;
if ( t ) {
lay : : TechnologyComponentEditor * tce_widget = new TechBaseEditorPage ( this ) ;
2017-04-15 01:03:24 +02:00
tce_widget - > setEnabled ( ! t - > is_readonly ( ) ) ;
2017-02-12 13:21:08 +01:00
tce_widget - > set_technology ( t , 0 ) ;
tc_stack - > addWidget ( tce_widget ) ;
m_component_editors . insert ( std : : make_pair ( std : : string ( " _general " ) , tce_widget ) ) ;
2017-04-15 01:03:24 +02:00
if ( lay : : MacroController : : instance ( ) ) {
const std : : vector < std : : pair < std : : string , std : : string > > & mc = lay : : MacroController : : instance ( ) - > macro_categories ( ) ;
for ( std : : vector < std : : pair < std : : string , std : : string > > : : const_iterator c = mc . begin ( ) ; c ! = mc . end ( ) ; + + c ) {
tce_widget = new TechMacrosPage ( this , c - > first , c - > second ) ;
tce_widget - > setEnabled ( ! t - > is_readonly ( ) ) ;
tce_widget - > set_technology ( t , 0 ) ;
tc_stack - > addWidget ( tce_widget ) ;
m_component_editors . insert ( std : : make_pair ( std : : string ( " _macros_ " ) + c - > first , tce_widget ) ) ;
}
2017-02-12 13:21:08 +01:00
}
tce_widget = new TechLoadOptionsEditorPage ( this ) ;
2017-04-15 01:03:24 +02:00
tce_widget - > setEnabled ( ! t - > is_readonly ( ) ) ;
2017-02-12 13:21:08 +01:00
tce_widget - > set_technology ( t , 0 ) ;
tc_stack - > addWidget ( tce_widget ) ;
m_component_editors . insert ( std : : make_pair ( std : : string ( " _load_options " ) , tce_widget ) ) ;
tce_widget = new TechSaveOptionsEditorPage ( this ) ;
2017-04-15 01:03:24 +02:00
tce_widget - > setEnabled ( ! t - > is_readonly ( ) ) ;
2017-02-12 13:21:08 +01:00
tce_widget - > set_technology ( t , 0 ) ;
tc_stack - > addWidget ( tce_widget ) ;
m_component_editors . insert ( std : : make_pair ( std : : string ( " _save_options " ) , tce_widget ) ) ;
std : : vector < std : : string > tc_names = t - > component_names ( ) ;
for ( std : : vector < std : : string > : : const_iterator n = tc_names . begin ( ) ; n ! = tc_names . end ( ) ; + + n ) {
TechnologyComponent * tc = t - > component_by_name ( * n ) - > clone ( ) ;
m_technology_components . insert ( std : : make_pair ( * n , tc ) ) ;
tce_widget = tc - > create_editor ( this ) ;
if ( tce_widget ) {
2017-04-15 01:03:24 +02:00
tce_widget - > setEnabled ( ! t - > is_readonly ( ) ) ;
2017-02-12 13:21:08 +01:00
tce_widget - > set_technology ( t , tc ) ;
tc_stack - > addWidget ( tce_widget ) ;
m_component_editors . insert ( std : : make_pair ( tc - > name ( ) , tce_widget ) ) ;
}
}
}
}
void
TechSetupDialog : : update_tech_component ( )
{
std : : string tc_name = selected_tech_component_name ( ) ;
std : : map < std : : string , lay : : TechnologyComponentEditor * > : : const_iterator tce = m_component_editors . find ( tc_name ) ;
if ( tce ! = m_component_editors . end ( ) ) {
std : : map < std : : string , lay : : TechnologyComponent * > : : const_iterator tc = m_technology_components . find ( tc_name ) ;
if ( tc ! = m_technology_components . end ( ) ) {
mp_current_tech_component = tc - > second ;
} else {
mp_current_tech_component = 0 ;
}
tc_stack - > setCurrentWidget ( tce - > second ) ;
mp_current_editor = tce - > second ;
tce - > second - > setup ( ) ;
} else {
tc_stack - > setCurrentIndex ( 0 ) ;
mp_current_editor = 0 ;
}
}
void
TechSetupDialog : : select_tech ( const lay : : Technology & tech )
{
// unselect the previous technology
update_tech ( 0 ) ;
// find the item for the new technology
QTreeWidgetItem * item = 0 ;
for ( int i = tech_tree - > topLevelItemCount ( ) ; i > 0 ; - - i ) {
item = tech_tree - > topLevelItem ( i - 1 ) ;
if ( item - > data ( 0 , Qt : : UserRole ) . toString ( ) = = tl : : to_qstring ( tech . name ( ) ) ) {
break ;
}
}
tech_tree - > setCurrentItem ( item ) ;
update_tech ( selected_tech ( ) ) ;
update_tech_component ( ) ;
}
void
TechSetupDialog : : accept ( )
{
BEGIN_PROTECTED
commit_tech_component ( ) ;
QDialog : : accept ( ) ;
END_PROTECTED
}
void
TechSetupDialog : : current_tech_changed ( QTreeWidgetItem * current , QTreeWidgetItem * previous )
{
BEGIN_PROTECTED
try {
if ( current ) {
commit_tech_component ( ) ;
update_tech ( selected_tech ( ) ) ;
update_tech_component ( ) ;
}
} catch ( . . . ) {
disconnect ( tech_tree , SIGNAL ( currentItemChanged ( QTreeWidgetItem * , QTreeWidgetItem * ) ) , this , SLOT ( current_tech_changed ( QTreeWidgetItem * , QTreeWidgetItem * ) ) ) ;
// TODO: this leaves current selected - any way to unselect it?
tech_tree - > setCurrentItem ( previous ) ;
connect ( tech_tree , SIGNAL ( currentItemChanged ( QTreeWidgetItem * , QTreeWidgetItem * ) ) , this , SLOT ( current_tech_changed ( QTreeWidgetItem * , QTreeWidgetItem * ) ) ) ;
throw ;
}
END_PROTECTED
}
void
TechSetupDialog : : commit_tech_component ( )
{
if ( mp_current_editor ) {
mp_current_editor - > commit ( ) ;
}
2017-04-15 01:03:24 +02:00
if ( mp_current_tech & & mp_current_tech_component & & ! mp_current_tech - > is_readonly ( ) ) {
2017-02-12 13:21:08 +01:00
mp_current_tech - > set_component ( mp_current_tech_component - > clone ( ) ) ;
// because commit may have changed the description text, update the technology titles
for ( int i = tech_tree - > topLevelItemCount ( ) ; i > 0 ; - - i ) {
QTreeWidgetItem * item = tech_tree - > topLevelItem ( i - 1 ) ;
lay : : Technology * t = m_technologies . technology_by_name ( tl : : to_string ( item - > data ( 0 , Qt : : UserRole ) . toString ( ) ) ) ;
std : : string d = t - > name ( ) ;
if ( ! d . empty ( ) & & ! t - > description ( ) . empty ( ) ) {
d + = " - " ;
}
d + = t - > description ( ) ;
item - > setData ( 0 , Qt : : DisplayRole , QVariant ( tl : : to_qstring ( d ) ) ) ;
}
}
}
std : : string
TechSetupDialog : : selected_tech_component_name ( )
{
QTreeWidgetItem * item = tech_tree - > currentItem ( ) ;
if ( item ) {
QVariant d = item - > data ( 0 , Qt : : UserRole + 1 ) ;
if ( d ! = QVariant ( ) ) {
return tl : : to_string ( d . toString ( ) ) ;
}
}
return std : : string ( ) ;
}
lay : : Technology *
TechSetupDialog : : selected_tech ( )
{
QTreeWidgetItem * item = tech_tree - > currentItem ( ) ;
while ( item ) {
QVariant d = item - > data ( 0 , Qt : : UserRole ) ;
if ( d ! = QVariant ( ) ) {
std : : string tn = tl : : to_string ( d . toString ( ) ) ;
if ( m_technologies . has_technology ( tn ) ) {
return m_technologies . technology_by_name ( tn ) ;
}
}
// try parent node.
item = item - > parent ( ) ;
}
return 0 ;
}
// ----------------------------------------------------------------
// TechComponentSetupDialog implementation
TechComponentSetupDialog : : TechComponentSetupDialog ( QWidget * parent , Technology * tech , const std : : string & component_name )
: QDialog ( parent ) ,
mp_tech ( tech ) , mp_component ( 0 ) , mp_editor ( 0 )
{
setObjectName ( QString : : fromUtf8 ( " tech_component_setup_dialog " ) ) ;
Ui : : TechComponentSetupDialog : : setupUi ( this ) ;
if ( tech - > name ( ) . empty ( ) ) {
setWindowTitle ( tl : : to_qstring ( tl : : to_string ( QObject : : tr ( " Edit Technology " ) ) + " - " + tl : : to_string ( QObject : : tr ( " (Default) " ) ) ) ) ;
} else {
setWindowTitle ( tl : : to_qstring ( tl : : to_string ( QObject : : tr ( " Edit Technology " ) ) + " - " + tech - > name ( ) ) ) ;
}
const TechnologyComponent * component = tech - > component_by_name ( component_name ) ;
if ( component ) {
mp_component = component - > clone ( ) ;
mp_editor = mp_component - > create_editor ( content_frame ) ;
if ( mp_editor ) {
QVBoxLayout * layout = new QVBoxLayout ( content_frame ) ;
layout - > addWidget ( mp_editor ) ;
layout - > setMargin ( 0 ) ;
content_frame - > setLayout ( layout ) ;
mp_editor - > set_technology ( tech , mp_component ) ;
mp_editor - > setup ( ) ;
}
}
}
TechComponentSetupDialog : : ~ TechComponentSetupDialog ( )
{
delete mp_component ;
mp_component = 0 ;
}
void
TechComponentSetupDialog : : accept ( )
{
BEGIN_PROTECTED
if ( mp_editor & & mp_tech & & mp_component ) {
mp_editor - > commit ( ) ;
mp_tech - > set_component ( mp_component ) ;
mp_component = 0 ;
}
QDialog : : accept ( ) ;
END_PROTECTED
}
}