/*************************************************************************** * Copyright (C) 2003-2005 * * Jason Kivlighn (jkivlighn@gmail.com) * * * * 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. * ***************************************************************************/ #include "setupdisplay.h" #include <tdeapplication.h> #include <tdeconfig.h> #include <kdebug.h> #include <tdefontdialog.h> #include <kcolordialog.h> #include <tdelocale.h> #include <tdepopupmenu.h> #include <kiconloader.h> #include <kstandarddirs.h> #include <tdetempfile.h> #include <tdehtmlview.h> #include <dom/dom_doc.h> #include <dom/css_rule.h> #include <tqinputdialog.h> #include <tqaction.h> #include <tqlabel.h> #include <tqfile.h> #include <tqregexp.h> #include <tqtextedit.h> #include <tqtooltip.h> #include <tqobjectlist.h> #include <tqvaluelist.h> #include <tqlayout.h> #include "datablocks/mixednumber.h" #include "dialogs/borderdialog.h" #include "exporters/htmlexporter.h" #include <cmath> KreDisplayItem::KreDisplayItem( const TQString &n, const TQString &_name ) : nodeId(n), name(_name) { clear(); } void KreDisplayItem::clear() { alignment = TQt::AlignHCenter; show = true; backgroundColor = TQColor(255,255,255); textColor = TQColor(0,0,0); columns = 1; } SetupDisplay::SetupDisplay( const Recipe &sample, TQWidget *parent ) : TDEHTMLPart(parent), box_properties( new PropertiesMap ), node_item_map( new TQMap<TQString, KreDisplayItem*> ), has_changes( false ), popup(0) { connect( this, TQ_SIGNAL( popupMenu(const TQString &,const TQPoint &) ), TQ_SLOT( nodeClicked(const TQString &,const TQPoint &) ) ); if ( sample.recipeID != -1 ) m_sample = sample; else { m_sample.title = i18n("Recipe Title"); m_sample.yield.amount = 0; m_sample.categoryList.append( Element(i18n( "Category 1, Category 2, ..." ) ) ); m_sample.instructions = i18n("Instructions"); m_sample.prepTime = TQTime(0,0); m_sample.authorList.append( Element(i18n( "Author 1, Author 2, ..." )) ); Ingredient ing; ing.name = i18n("Ingredient 1"); m_sample.ingList.append( ing ); ing.name = i18n("Ingredient 2"); m_sample.ingList.append( ing ); ing.name = "..."; m_sample.ingList.append( ing ); RatingCriteria rc; Rating rating1; rating1.rater = i18n("Rater"); rating1.comment = i18n("Comment"); rc.name = i18n("Criteria 1"); rc.stars = 5.0; rating1.append(rc); rc.name = i18n("Criteria 2"); rc.stars = 2.5; rating1.append(rc); IngredientProperty prop; prop.name = i18n("Property 1"); m_sample.properties.append(prop); prop.name = i18n("Property 2"); m_sample.properties.append(prop); prop.name = "..."; m_sample.properties.append(prop); m_sample.ratingList.append(rating1); } kdDebug()<<"first load"<<endl; loadHTMLView(); show(); createItem( "background", i18n("Background"), BackgroundColor ); createItem( "title", i18n("Title"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border ); createItem( "instructions", i18n("Instructions"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border ); createItem( "prep_time", i18n("Preparation Time"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border ); createItem( "photo", i18n("Photo"), Visibility | Border ); createItem( "authors", i18n("Authors"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border ); createItem( "categories", i18n("Categories"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border ); createItem( "ingredients", i18n("Ingredients"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border | Columns ); createItem( "properties", i18n("Properties"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border | Columns ); createItem( "ratings", i18n("Ratings"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border ); createItem( "yield", i18n("Yield"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border ); } SetupDisplay::~SetupDisplay() { delete box_properties; delete node_item_map; } void SetupDisplay::loadHTMLView( const TQString &templateFile, const TQString &styleFile ) { kdDebug()<<"loading template: "<<templateFile<<" style: "<<styleFile<<endl; TQString tmp_filename = locateLocal( "tmp", "krecipes_recipe_view" ); HTMLExporter exporter( tmp_filename + ".html", "html" ); if ( templateFile != TQString::null ) exporter.setTemplate( templateFile ); if ( styleFile != TQString::null ) exporter.setStyle( styleFile ); RecipeList recipeList; recipeList.append(m_sample); TQFile file(tmp_filename + ".html"); if ( file.open( IO_WriteOnly ) ) { TQTextStream stream(&file); exporter.writeStream(stream,recipeList); } else { kdDebug()<<"Unable to open file for writing"<<endl; } file.close(); KURL url; url.setPath( tmp_filename + ".html" ); openURL( url ); kdDebug() << "Opening URL: " << url.htmlURL() << endl; } void SetupDisplay::reload() { loadHTMLView( m_activeTemplate, m_activeStyle ); } void SetupDisplay::loadTemplate( const TQString &filename ) { bool storeChangedState = has_changes; KTempFile tmpFile; saveLayout(tmpFile.name()); has_changes = storeChangedState; //saveLayout() sets changes to false loadHTMLView( filename, tmpFile.name() ); m_activeTemplate = filename; } void SetupDisplay::createItem( const TQString &node, const TQString &name, unsigned int properties ) { KreDisplayItem * item = new KreDisplayItem( node, name ); box_properties->insert( item, properties ); node_item_map->insert( node, item ); } void SetupDisplay::loadLayout( const TQString &filename ) { TQFile input( filename ); if ( input.open( IO_ReadOnly ) ) { TQDomDocument doc; TQString error; int line; int column; if ( !doc.setContent( &input, &error, &line, &column ) ) { kdDebug() << TQString( i18n( "\"%1\" at line %2, column %3. This may not be a Krecipes layout file." ) ).arg( error ).arg( line ).arg( column ) << endl; return ; } m_styleSheet = DOM::CSSStyleSheet(); TQMap<TQString,KreDisplayItem*>::iterator it; for ( it = node_item_map->begin(); it != node_item_map->end(); ++it ) { it.data()->clear(); } processDocument( doc ); loadHTMLView(m_activeTemplate, filename); m_activeStyle = filename; has_changes = false; } else kdDebug() << "Unable to open file: " << filename << endl; } void SetupDisplay::beginObject( const TQString &object ) { TQMap<TQString, KreDisplayItem*>::iterator map_it = node_item_map->find( object ); if ( map_it != node_item_map->end() ) m_currentItem = map_it.data(); else m_currentItem = 0; } void SetupDisplay::endObject() { m_currentItem = 0; } void SetupDisplay::loadBackgroundColor( const TQString &object, const TQColor &color ) { if ( m_currentItem ) { m_currentItem->backgroundColor = color; m_styleSheet.insertRule("."+object+" { "+bgColorAsCSS(color)+" }",m_styleSheet.cssRules().length()); } } void SetupDisplay::loadFont( const TQString &object, const TQFont &font ) { if ( m_currentItem ) { m_currentItem->font = font; m_styleSheet.insertRule("."+object+" { "+fontAsCSS(font)+" }",m_styleSheet.cssRules().length()); } } void SetupDisplay::loadTextColor( const TQString &object, const TQColor &color ) { if ( m_currentItem ) { m_currentItem->textColor = color; m_styleSheet.insertRule("."+object+" { "+textColorAsCSS(color)+" }",m_styleSheet.cssRules().length()); } } void SetupDisplay::loadVisibility( const TQString &object, bool visible ) { if ( m_currentItem ) { m_currentItem->show = visible; emit itemVisibilityChanged( m_currentItem, visible ); m_styleSheet.insertRule("."+object+" { "+visibilityAsCSS(visible)+" }",m_styleSheet.cssRules().length()); } } void SetupDisplay::loadAlignment( const TQString &object, int alignment ) { if ( m_currentItem ) { m_currentItem->alignment = alignment; m_styleSheet.insertRule("."+object+" { "+alignmentAsCSS(alignment)+" }",m_styleSheet.cssRules().length()); } } void SetupDisplay::loadBorder( const TQString &object, const KreBorder& border ) { if ( m_currentItem ) { m_currentItem->border = border; m_styleSheet.insertRule("."+object+" { "+borderAsCSS(border)+" }",m_styleSheet.cssRules().length()); } } void SetupDisplay::loadColumns( const TQString &/*object*/, int cols ) { if ( m_currentItem ) { m_currentItem->columns = cols; } } void SetupDisplay::saveLayout( const TQString &filename ) { TQDomImplementation dom_imp; TQDomDocument doc = dom_imp.createDocument( TQString::null, "krecipes-layout", dom_imp.createDocumentType( "krecipes-layout", TQString::null, TQString::null ) ); TQDomElement layout_tag = doc.documentElement(); layout_tag.setAttribute( "version", 0.4 ); //layout_tag.setAttribute( "generator", TQString("Krecipes v%1").arg(krecipes_version()) ); doc.appendChild( layout_tag ); for ( TQMap<TQString, KreDisplayItem*>::const_iterator it = node_item_map->begin(); it != node_item_map->end(); ++it ) { TQDomElement base_tag = doc.createElement( it.key() ); layout_tag.appendChild( base_tag ); int properties = (*box_properties)[it.data()]; if ( properties & BackgroundColor ) { TQDomElement backgroundcolor_tag = doc.createElement( "background-color" ); backgroundcolor_tag.appendChild( doc.createTextNode( it.data()->backgroundColor.name() ) ); base_tag.appendChild( backgroundcolor_tag ); } if ( properties & TextColor ) { TQDomElement textcolor_tag = doc.createElement( "text-color" ); textcolor_tag.appendChild( doc.createTextNode( it.data()->textColor.name() ) ); base_tag.appendChild( textcolor_tag ); } if ( properties & Font ) { TQDomElement font_tag = doc.createElement( "font" ); font_tag.appendChild( doc.createTextNode( it.data()->font.toString() ) ); base_tag.appendChild( font_tag ); } if ( properties & Visibility ) { TQDomElement visibility_tag = doc.createElement( "visible" ); visibility_tag.appendChild( doc.createTextNode( (it.data()->show) ? "true" : "false" ) ); base_tag.appendChild( visibility_tag ); } if ( properties & Alignment ) { TQDomElement alignment_tag = doc.createElement( "alignment" ); alignment_tag.appendChild( doc.createTextNode( TQString::number( it.data()->alignment ) ) ); base_tag.appendChild( alignment_tag ); } if ( properties & Border ) { TQDomElement border_tag = doc.createElement( "border" ); border_tag.setAttribute( "width", it.data()->border.width ); border_tag.setAttribute( "style", it.data()->border.style ); border_tag.setAttribute( "color", it.data()->border.color.name() ); base_tag.appendChild( border_tag ); } if ( properties & Columns ) { TQDomElement columns_tag = doc.createElement( "columns" ); columns_tag.appendChild( doc.createTextNode( TQString::number( it.data()->columns ) ) ); base_tag.appendChild( columns_tag ); } } TQFile out_file( filename ); if ( out_file.open( IO_WriteOnly ) ) { has_changes = false; TQTextStream stream( &out_file ); stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" << doc.toString(); } else kdDebug() << "Error: Unable to write to file " << filename << endl; } void SetupDisplay::begin(const KURL &url, int xOffset, int yOffset) { kdDebug()<<"begin"<<endl; TDEHTMLPart::begin(url,xOffset,yOffset); kdDebug()<<"end"<<endl; DOM::Document doc = document(); DOM::DOMImplementation impl = doc.implementation(); kdDebug() << "(1) document: " << document().handle() << endl; #if 0 if ( !impl.isNull() ) { //m_styleSheet = impl.createCSSStyleSheet("-krecipes","screen"); //m_styleSheet = DOM::CSSStyleSheet(); //doc.addStyleSheet(m_styleSheet); //applyStylesheet(); } #endif } void SetupDisplay::nodeClicked(const TQString &/*url*/,const TQPoint &point) { DOM::Node node = nodeUnderMouse(); DOM::Element element; if ( node.nodeType() != DOM::Node::ELEMENT_NODE ) { kdDebug()<<"not an element"<<endl; element = (DOM::Element)node.parentNode(); } else element = (DOM::Element)node; while ( !element.parentNode().isNull() ) { if ( element.hasAttribute("class") ) { TQString id = element.getAttribute("class").string(); if ( node_item_map->keys().contains(id) ) break; } element = (DOM::Element)element.parentNode(); } m_currNodeId = element.getAttribute("class").string(); if ( m_currNodeId.isEmpty() ) { kdDebug()<<"Code error: unable to determine class of selected element"<<endl; return; } KreDisplayItem *item = *node_item_map->find( m_currNodeId ); delete popup; popup = new TDEPopupMenu( view() ); popup->insertTitle( item->name ); unsigned int properties = 0; for ( PropertiesMap::const_iterator it = box_properties->begin(); it != box_properties->end(); ++it ) { if ( it.key()->nodeId == m_currNodeId ) { properties = it.data(); break; } } TDEIconLoader il; if ( properties & BackgroundColor ) popup->insertItem( i18n( "Background Color..." ), this, TQ_SLOT( setBackgroundColor() ) ); if ( properties & TextColor ) popup->insertItem( i18n( "Text Color..." ), this, TQ_SLOT( setTextColor() ) ); if ( properties & Font ) popup->insertItem( il.loadIconSet( "text", TDEIcon::Small, 16 ), i18n( "Font..." ), this, TQ_SLOT( setFont() ) ); if ( properties & Visibility ) { int id = popup->insertItem( i18n( "Show" ), this, TQ_SLOT( setShown( int ) ) ); popup->setItemChecked( id, item->show ); } if ( properties & Alignment ) { TQPopupMenu * sub_popup = new TQPopupMenu( popup ); TQActionGroup *alignment_actions = new TQActionGroup( this ); alignment_actions->setExclusive( true ); TQAction *c_action = new TQAction( i18n( "Center" ), i18n( "Center" ), 0, alignment_actions, 0, true ); TQAction *l_action = new TQAction( i18n( "Left" ), i18n( "Left" ), 0, alignment_actions, 0, true ); TQAction *r_action = new TQAction( i18n( "Right" ), i18n( "Right" ), 0, alignment_actions, 0, true ); int align = item->alignment; if ( align & TQt::AlignHCenter ) c_action->setOn(true); if ( align & TQt::AlignLeft ) l_action->setOn(true); if ( align & TQt::AlignRight ) r_action->setOn(true); connect( alignment_actions, TQ_SIGNAL( selected( TQAction* ) ), TQ_SLOT( setAlignment( TQAction* ) ) ); popup->insertItem( i18n( "Alignment" ), sub_popup ); alignment_actions->addTo( sub_popup ); } if ( properties & Border ) popup->insertItem( i18n( "Border..." ), this, TQ_SLOT( setBorder() ) ); if ( properties & Columns ) popup->insertItem( i18n( "Columns..." ), this, TQ_SLOT( setColumns() ) ); popup->popup( point ); } void SetupDisplay::applyStylesheet() { loadTemplate( m_activeTemplate ); if ( !document().isNull() && !m_styleSheet.isNull() ) { //document().removeStyleSheet(m_styleSheet); //document().addStyleSheet(m_styleSheet); } } void SetupDisplay::setBackgroundColor() { KreDisplayItem *item = *node_item_map->find( m_currNodeId ); if ( KColorDialog::getColor( item->backgroundColor, view() ) == TQDialog::Accepted ) { m_currentItem = item; loadBackgroundColor(m_currNodeId,item->backgroundColor); m_currentItem = 0; applyStylesheet(); has_changes = true; } } void SetupDisplay::setBorder() { KreDisplayItem *item = *node_item_map->find( m_currNodeId ); BorderDialog borderDialog( item->border, view() ); if ( borderDialog.exec() == TQDialog::Accepted ) { m_currentItem = item; loadBorder( m_currNodeId, borderDialog.border() ); m_currentItem = 0; applyStylesheet(); has_changes = true; } } void SetupDisplay::setColumns() { KreDisplayItem *item = *node_item_map->find( m_currNodeId ); int cols = TQInputDialog::getInteger( TQString::null, i18n("Select the number of columns to use:"), item->columns, 1, 100, 1, 0, view() ); if ( cols > 0 ) { m_currentItem = item; loadColumns( m_currNodeId, cols ); m_currentItem = 0; loadTemplate( m_activeTemplate ); has_changes = true; } } void SetupDisplay::setTextColor() { KreDisplayItem *item = *node_item_map->find( m_currNodeId ); if ( KColorDialog::getColor( item->textColor, view() ) == TQDialog::Accepted ) { m_currentItem = item; loadTextColor(m_currNodeId,item->textColor); m_currentItem = 0; applyStylesheet(); has_changes = true; } } void SetupDisplay::setShown( int id ) { KreDisplayItem *item = *node_item_map->find( m_currNodeId ); emit itemVisibilityChanged( item, !popup->isItemChecked( id ) ); m_currentItem = item; loadVisibility(m_currNodeId,!popup->isItemChecked( id )); m_currentItem = 0; applyStylesheet(); has_changes = true; } void SetupDisplay::setFont() { KreDisplayItem *item = *node_item_map->find( m_currNodeId ); if ( TDEFontDialog::getFont( item->font, false, view() ) == TQDialog::Accepted ) { m_currentItem = item; loadFont(m_currNodeId,item->font); m_currentItem = 0; applyStylesheet(); has_changes = true; } } void SetupDisplay::setAlignment( TQAction *action ) { KreDisplayItem *item = *node_item_map->find( m_currNodeId ); //TODO: isn't there a simpler way to do this... //preserve non-horizontal alignment flags if ( item->alignment & TQt::AlignRight ) item->alignment ^= TQt::AlignRight; if ( item->alignment & TQt::AlignHCenter ) item->alignment ^= TQt::AlignHCenter; if ( item->alignment & TQt::AlignLeft ) item->alignment ^= TQt::AlignLeft; if ( action->text() == i18n( "Center" ) ) item->alignment |= TQt::AlignHCenter; else if ( action->text() == i18n( "Left" ) ) item->alignment |= TQt::AlignLeft; else if ( action->text() == i18n( "Right" ) ) item->alignment |= TQt::AlignRight; m_currentItem = item; loadAlignment(m_currNodeId,item->alignment); m_currentItem = 0; applyStylesheet(); has_changes = true; } void SetupDisplay::setItemShown( KreDisplayItem *item, bool visible ) { item->show = visible; m_styleSheet.insertRule("."+item->nodeId+" { visibility:"+(item->show?"visible":"hidden")+" }",m_styleSheet.cssRules().length()); applyStylesheet(); has_changes = true; } void SetupDisplay::changeMade( void ) { has_changes = true; } #include "setupdisplay.moc"