|
|
|
/*
|
|
|
|
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 Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
---
|
|
|
|
Copyright (C) 2004, Anders Lund <anders@alweb.dk>
|
|
|
|
*/
|
|
|
|
|
|
|
|
//BEGIN Includes
|
|
|
|
#include "filetemplates.h"
|
|
|
|
|
|
|
|
#include <kate/document.h>
|
|
|
|
|
|
|
|
#include <kaboutdata.h>
|
|
|
|
#include <kaction.h>
|
|
|
|
#include <kactioncollection.h>
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <kdialogbase.h>
|
|
|
|
#include <kdirwatch.h>
|
|
|
|
#include <kfiledialog.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kicondialog.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <kio/netaccess.h>
|
|
|
|
#include <klistview.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <knewstuff/knewstuff.h>
|
|
|
|
#include <knewstuff/entry.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <ktempfile.h>
|
|
|
|
#include <kurlrequester.h>
|
|
|
|
#include <kuser.h>
|
|
|
|
#include <kxmlguifactory.h>
|
|
|
|
|
|
|
|
#include <tqbuttongroup.h>
|
|
|
|
#include <tqcheckbox.h>
|
|
|
|
#include <tqcombobox.h>
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqdatetime.h>
|
|
|
|
#include <tqdict.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqlineedit.h>
|
|
|
|
#include <tqpopupmenu.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <tqradiobutton.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqstyle.h>
|
|
|
|
#include <tqwhatsthis.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tdetexteditor/templateinterface.h>
|
|
|
|
//END Includes
|
|
|
|
|
|
|
|
//BEGIN plugin + factory stuff
|
|
|
|
class PluginView : public KXMLGUIClient
|
|
|
|
{
|
|
|
|
friend class KateFileTemplates;
|
|
|
|
|
|
|
|
public:
|
|
|
|
Kate::MainWindow *win;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
void* init_katefiletemplates()
|
|
|
|
{
|
|
|
|
TDEGlobal::locale()->insertCatalogue("katefiletemplates");
|
|
|
|
return new KatePluginFactory;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KatePluginFactory::KatePluginFactory()
|
|
|
|
{
|
|
|
|
s_instance = new TDEInstance( "kate" );
|
|
|
|
}
|
|
|
|
|
|
|
|
KatePluginFactory::~KatePluginFactory()
|
|
|
|
{
|
|
|
|
delete s_instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQObject* KatePluginFactory::createObject( TQObject* parent, const char* name, const char*, const TQStringList & )
|
|
|
|
{
|
|
|
|
return new KateFileTemplates( parent, name );
|
|
|
|
}
|
|
|
|
|
|
|
|
TDEInstance* KatePluginFactory::s_instance = 0L;
|
|
|
|
//END
|
|
|
|
|
|
|
|
//BEGIN TemplateInfo
|
|
|
|
class TemplateInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TemplateInfo( const TQString& fn, const TQString &t, const TQString &g )
|
|
|
|
: filename( fn ), tmplate ( t ), group( g ) { ; }
|
|
|
|
~TemplateInfo() { ; }
|
|
|
|
|
|
|
|
TQString filename;
|
|
|
|
TQString tmplate;
|
|
|
|
TQString group;
|
|
|
|
TQString description;
|
|
|
|
TQString author;
|
|
|
|
TQString highlight;
|
|
|
|
TQString icon;
|
|
|
|
};
|
|
|
|
//END TemplateInfo
|
|
|
|
|
|
|
|
//BEGIN KateFileTemplates
|
|
|
|
KateFileTemplates::KateFileTemplates( TQObject* parent, const char* name )
|
|
|
|
: Kate::Plugin ( (Kate::Application*)parent, name ),
|
|
|
|
m_actionCollection( new KActionCollection( this, "template_actions", new TDEInstance("kate") ) )
|
|
|
|
{
|
|
|
|
// create actions, so that they are shared.
|
|
|
|
// We plug them into each view's menus, and update them centrally, so that
|
|
|
|
// new plugins can automatically become visible in all windows.
|
|
|
|
(void) new KAction ( i18n("Any File..."), 0, this,
|
|
|
|
TQT_SLOT( slotAny() ), m_actionCollection,
|
|
|
|
"file_template_any" );
|
|
|
|
// recent templates
|
|
|
|
m_acRecentTemplates = new KRecentFilesAction( i18n("&Use Recent"), 0, this,
|
|
|
|
TQT_SLOT(slotOpenTemplate(const KURL &)),
|
|
|
|
m_actionCollection,
|
|
|
|
"file_templates_recent" );
|
|
|
|
m_acRecentTemplates->loadEntries( kapp->config(), "Recent Templates" );
|
|
|
|
|
|
|
|
// template menu
|
|
|
|
m_dw = new KDirWatch( this, "template_dirwatch" );
|
|
|
|
TQStringList dirs = TDEGlobal::dirs()->findDirs("data", "kate/plugins/katefiletemplates/templates");
|
|
|
|
for ( TQStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it )
|
|
|
|
{
|
|
|
|
m_dw->addDir( *it, true );
|
|
|
|
}
|
|
|
|
|
|
|
|
connect( m_dw, TQT_SIGNAL(dirty(const TQString&)),
|
|
|
|
this, TQT_SLOT(updateTemplateDirs(const TQString&)) );
|
|
|
|
connect( m_dw, TQT_SIGNAL(created(const TQString&)),
|
|
|
|
this, TQT_SLOT(updateTemplateDirs(const TQString&)) );
|
|
|
|
connect( m_dw, TQT_SIGNAL(deleted(const TQString&)),
|
|
|
|
this, TQT_SLOT(updateTemplateDirs(const TQString&)) );
|
|
|
|
|
|
|
|
m_templates.setAutoDelete( true );
|
|
|
|
updateTemplateDirs();
|
|
|
|
|
|
|
|
m_user = 0;
|
|
|
|
m_emailstuff = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called whenever the template dir is changed. Recreates the templates list.
|
|
|
|
*/
|
|
|
|
void KateFileTemplates::updateTemplateDirs(const TQString &d)
|
|
|
|
{
|
|
|
|
kdDebug()<<"updateTemplateDirs called with arg "<<d<<endl;
|
|
|
|
|
|
|
|
TQStringList templates = TDEGlobal::dirs()->findAllResources(
|
|
|
|
"data","kate/plugins/katefiletemplates/templates/*.katetemplate",
|
|
|
|
false,true);
|
|
|
|
|
|
|
|
m_templates.clear();
|
|
|
|
|
|
|
|
TQRegExp re( "\\b(\\w+)\\s*=\\s*(.+)(?:\\s+\\w+=|$)" );
|
|
|
|
re.setMinimal( true );
|
|
|
|
|
|
|
|
TDEConfig *config = kapp->config();
|
|
|
|
TQStringList hidden;
|
|
|
|
config->readListEntry( "Hidden", hidden, ';' );
|
|
|
|
|
|
|
|
for ( TQStringList::Iterator it=templates.begin(); it != templates.end(); ++it )
|
|
|
|
{
|
|
|
|
TQFile _f( *it );
|
|
|
|
if ( _f.open( IO_ReadOnly ) )
|
|
|
|
{
|
|
|
|
TQString fname = (*it).section( '/', -1 );
|
|
|
|
|
|
|
|
// skip if hidden
|
|
|
|
if ( hidden.contains( fname ) )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Read the first line of the file, to get the group/name
|
|
|
|
TemplateInfo *tmp = new TemplateInfo( *it, fname, "Other" );
|
|
|
|
bool trymore ( true );
|
|
|
|
TQTextStream stream(&_f);
|
|
|
|
while ( trymore )
|
|
|
|
{
|
|
|
|
TQString _line = stream.readLine();
|
|
|
|
trymore = _line.startsWith( "katetemplate:" );
|
|
|
|
if ( ! trymore ) break;
|
|
|
|
|
|
|
|
int pos ( 0 );
|
|
|
|
while ( ( ( pos = re.search( _line, pos ) ) >= 0 ) )
|
|
|
|
{
|
|
|
|
pos += re.cap( 1 ).length();
|
|
|
|
if ( re.cap( 1 ).lower() == "template" )
|
|
|
|
tmp->tmplate = re.cap( 2 );
|
|
|
|
if ( re.cap( 1 ).lower() == "group" )
|
|
|
|
tmp->group = re.cap( 2 );
|
|
|
|
if ( re.cap( 1 ).lower() == "description" )
|
|
|
|
tmp->description = re.cap( 2 );
|
|
|
|
if ( re.cap( 1 ).lower() == "author" )
|
|
|
|
tmp->author = re.cap( 2 );
|
|
|
|
if ( re.cap( 1 ).lower() == "highlight" )
|
|
|
|
tmp->highlight = re.cap( 2 );
|
|
|
|
if ( re.cap( 1 ) == "icon" )
|
|
|
|
tmp->icon = re.cap( 2 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_templates.append( tmp );
|
|
|
|
_f.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// update the menus of all views
|
|
|
|
for (uint z=0; z < m_views.count(); z++)
|
|
|
|
{
|
|
|
|
PluginView *view = m_views.at(z);
|
|
|
|
refreshMenu( view );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KateFileTemplates::~KateFileTemplates()
|
|
|
|
{
|
|
|
|
m_acRecentTemplates->saveEntries( kapp->config(), "Recent Templates" );
|
|
|
|
delete m_emailstuff;
|
|
|
|
delete m_user;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateFileTemplates::addView(Kate::MainWindow *win)
|
|
|
|
{
|
|
|
|
PluginView *view = new PluginView ();
|
|
|
|
|
|
|
|
(void) new KAction( i18n("&Manage Templates..."), 0,
|
|
|
|
this, TQT_SLOT(slotEditTemplate()),
|
|
|
|
view->actionCollection(), "settings_manage_templates" );
|
|
|
|
|
|
|
|
(void)new KActionMenu( i18n("New From &Template"), "make",
|
|
|
|
view->actionCollection(), "file_new_fromtemplate" );
|
|
|
|
refreshMenu( view );
|
|
|
|
|
|
|
|
view->setInstance (new TDEInstance("kate"));
|
|
|
|
view->setXMLFile("plugins/katefiletemplates/ui.rc");
|
|
|
|
win->guiFactory()->addClient (view);
|
|
|
|
view->win = win;
|
|
|
|
|
|
|
|
m_views.append (view);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateFileTemplates::removeView(Kate::MainWindow *win)
|
|
|
|
{
|
|
|
|
for (uint z=0; z < m_views.count(); z++)
|
|
|
|
if (m_views.at(z)->win == win)
|
|
|
|
{
|
|
|
|
PluginView *view = m_views.at(z);
|
|
|
|
m_views.remove (view);
|
|
|
|
win->guiFactory()->removeClient (view);
|
|
|
|
delete view;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList KateFileTemplates::groups()
|
|
|
|
{
|
|
|
|
TQStringList l;
|
|
|
|
TQString s;
|
|
|
|
|
|
|
|
for ( uint i = 0; i < m_templates.count(); i++ )
|
|
|
|
{
|
|
|
|
s = m_templates.at( i )->group;
|
|
|
|
if ( ! l.contains( s ) )
|
|
|
|
l.append( s );
|
|
|
|
}
|
|
|
|
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateFileTemplates::refreshMenu( PluginView *v )
|
|
|
|
{
|
|
|
|
TQPopupMenu *m = (TQPopupMenu*)(((KActionMenu*)(v->actionCollection()->action("file_new_fromtemplate")))->popupMenu());
|
|
|
|
|
|
|
|
// clear the menu for templates
|
|
|
|
m->clear();
|
|
|
|
|
|
|
|
// restore it
|
|
|
|
m_actionCollection->action( "file_template_any" )->plug( m );
|
|
|
|
m_acRecentTemplates->plug( m );
|
|
|
|
m->insertSeparator();
|
|
|
|
|
|
|
|
TQDict<TQPopupMenu> submenus; // ### TQMAP
|
|
|
|
for ( uint i = 0; i < m_templates.count(); i++ )
|
|
|
|
{
|
|
|
|
if ( ! submenus[ m_templates.at( i )->group ] )
|
|
|
|
{
|
|
|
|
TQPopupMenu *sm = new TQPopupMenu();
|
|
|
|
submenus.insert( m_templates.at( i )->group, sm );
|
|
|
|
m->insertItem( m_templates.at( i )->group, sm );
|
|
|
|
}
|
|
|
|
kdDebug()<<"=== ICON: '"<<m_templates.at( i )->icon<<"'"<<endl;
|
|
|
|
if ( ! m_templates.at( i )->icon.isEmpty() )
|
|
|
|
submenus[m_templates.at( i )->group]->insertItem(
|
|
|
|
SmallIconSet( m_templates.at( i )->icon ),
|
|
|
|
m_templates.at( i )->tmplate, this, TQT_SLOT(slotOpenTemplate( int )), 0, i );
|
|
|
|
else
|
|
|
|
submenus[m_templates.at( i )->group]->insertItem(
|
|
|
|
m_templates.at( i )->tmplate, this, TQT_SLOT(slotOpenTemplate( int )), 0, i );
|
|
|
|
|
|
|
|
// add whatsthis containing the description and author
|
|
|
|
TQString w ( m_templates.at( i )->description );
|
|
|
|
if( ! m_templates.at( i )->author.isEmpty() )
|
|
|
|
{
|
|
|
|
w.append( "<p>Author: " );
|
|
|
|
w.append( m_templates.at( i )->author );
|
|
|
|
}
|
|
|
|
if ( ! w.isEmpty() )
|
|
|
|
w.prepend( "<p>" );
|
|
|
|
|
|
|
|
if ( ! w.isEmpty() )
|
|
|
|
submenus[m_templates.at( i )->group]->findItem( i )->setWhatsThis( w );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Action slot: use any file as a template.
|
|
|
|
* Get a URL and pass it on.
|
|
|
|
*/
|
|
|
|
void KateFileTemplates::slotAny()
|
|
|
|
{
|
|
|
|
if (!application()->activeMainWindow())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// get a URL and pass that to slotOpenTemplate
|
|
|
|
TQString fn = KFileDialog::getOpenFileName(
|
|
|
|
"katefiletemplate",
|
|
|
|
TQString(),
|
|
|
|
application()->activeMainWindow()->viewManager()->activeView(),
|
|
|
|
i18n("Open as Template") );
|
|
|
|
if ( ! fn.isEmpty() )
|
|
|
|
slotOpenTemplate( KURL( fn ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* converts template [index] to a URL and passes that
|
|
|
|
*/
|
|
|
|
void KateFileTemplates::slotOpenTemplate( int index )
|
|
|
|
{
|
|
|
|
kdDebug()<<"slotOpenTemplate( "<<index<<" )"<<endl;
|
|
|
|
if ( index < 0 || (uint)index > m_templates.count() ) return;
|
|
|
|
slotOpenTemplate( KURL( m_templates.at( index )->filename ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateFileTemplates::slotOpenTemplate( const KURL &url )
|
|
|
|
{
|
|
|
|
// check if the file can be opened
|
|
|
|
TQString tmpfile;
|
|
|
|
TQString filename = url.fileName();
|
|
|
|
kdDebug()<<"file: "<<filename<<endl;
|
|
|
|
if ( TDEIO::NetAccess::download( url, tmpfile, 0L ) )
|
|
|
|
{
|
|
|
|
bool isTemplate ( filename.endsWith( ".katetemplate" ) );
|
|
|
|
TQString docname;
|
|
|
|
|
|
|
|
// open the file and parse for template variables and macros
|
|
|
|
TQFile file(tmpfile);
|
|
|
|
if ( ! file.open( IO_ReadOnly ) )
|
|
|
|
{
|
|
|
|
KMessageBox::sorry( application()->activeMainWindow()->viewManager()->activeView(),
|
|
|
|
i18n("<qt>Error opening the file<br><strong>%1</strong><br>for reading. The document will not be created.</qt>").arg(filename),
|
|
|
|
i18n("Template Plugin"), 0 );
|
|
|
|
TDEIO::NetAccess::removeTempFile( tmpfile );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// this may take a moment..
|
|
|
|
kapp->setOverrideCursor( TQCursor(TQCursor::WaitCursor) );
|
|
|
|
|
|
|
|
// create a new document
|
|
|
|
application()->activeMainWindow()->viewManager()->openURL( KURL() );
|
|
|
|
Kate::View *view = application()->activeMainWindow()->viewManager()->activeView();
|
|
|
|
Kate::Document *doc = view->getDoc();
|
|
|
|
|
|
|
|
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
TQString str, tmp;
|
|
|
|
uint numlines = 0;
|
|
|
|
uint doneheader = 0;
|
|
|
|
while ( !stream.eof() ) {
|
|
|
|
tmp = stream.readLine();
|
|
|
|
if ( ! numlines && isTemplate && tmp.startsWith( "katetemplate:" ) )
|
|
|
|
{
|
|
|
|
// look for document name, highlight
|
|
|
|
if ( ! (doneheader & 1) )
|
|
|
|
{
|
|
|
|
TQRegExp reName( "\\bdocumentname\\s*=\\s*(.+)(?:\\s+\\w+\\s*=|$)", false );
|
|
|
|
reName.setMinimal( true );
|
|
|
|
if ( reName.search( tmp ) > -1 )
|
|
|
|
{
|
|
|
|
docname = reName.cap( 1 );
|
|
|
|
docname = docname.replace( "%N", "%1" );
|
|
|
|
doneheader |= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ! (doneheader & 2) )
|
|
|
|
{
|
|
|
|
TQRegExp reHl( "\\bhighlight\\s*=\\s*(.+)(?:\\s+\\w+\\s*=|$)", false );
|
|
|
|
reHl.setMinimal( true );
|
|
|
|
kdDebug()<<"looking for a hl mode"<<endl;
|
|
|
|
if ( reHl.search( tmp ) > -1 )
|
|
|
|
{
|
|
|
|
kdDebug()<<"looking for a hl mode -- "<<reHl.cap()<<endl;
|
|
|
|
// this is overly complex, too bad the interface is
|
|
|
|
// not providing a resonable method..
|
|
|
|
TQString hlmode = reHl.cap( 1 );
|
|
|
|
uint _i = 0;
|
|
|
|
while ( _i < doc->hlModeCount() )
|
|
|
|
{
|
|
|
|
if ( doc->hlModeName( _i ) == hlmode )
|
|
|
|
{
|
|
|
|
doc->setHlMode( _i );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
_i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
doneheader |= 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
continue; // skip this line
|
|
|
|
}
|
|
|
|
if ( numlines )
|
|
|
|
str += "\n";
|
|
|
|
str += tmp;
|
|
|
|
numlines++;
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
TDEIO::NetAccess::removeTempFile( tmpfile );
|
|
|
|
|
|
|
|
uint line, col;
|
|
|
|
line = col = 0;
|
|
|
|
|
|
|
|
if ( ! isTemplate )
|
|
|
|
{
|
|
|
|
int d = filename.findRev('.');
|
|
|
|
docname = i18n("Untitled %1");
|
|
|
|
if ( d > 0 ) docname += filename.mid( d );
|
|
|
|
} else if ( docname.isEmpty() )
|
|
|
|
docname = filename.left( filename.length() - 13 );
|
|
|
|
|
|
|
|
// check for other documents matching this naming scheme,
|
|
|
|
// and do a count before chosing a name for this one
|
|
|
|
TQString p = docname;
|
|
|
|
p.replace( "%1", "\\d+" );
|
|
|
|
p.replace( ".", "\\." );
|
|
|
|
p.prepend( "^" );
|
|
|
|
p.append( "$" );
|
|
|
|
TQRegExp reName( p );
|
|
|
|
|
|
|
|
int count = 1;
|
|
|
|
for ( uint i=0; i < application()->documentManager()->documents(); i++ )
|
|
|
|
if ( ( reName.search ( application()->documentManager()->document( i )->docName() ) > -1 ) )
|
|
|
|
count++;
|
|
|
|
|
|
|
|
if ( docname.contains( "%1" ) )
|
|
|
|
docname = docname.arg( count );
|
|
|
|
|
|
|
|
doc->setDocName( docname );
|
|
|
|
|
|
|
|
doc->setModified( false );
|
|
|
|
|
|
|
|
kapp->restoreOverrideCursor();
|
|
|
|
m_acRecentTemplates->addURL( url );
|
|
|
|
|
|
|
|
// clean up
|
|
|
|
delete m_user;
|
|
|
|
m_user = 0;
|
|
|
|
delete m_emailstuff;
|
|
|
|
m_emailstuff = 0;
|
|
|
|
if (isTemplate) {
|
|
|
|
KTextEditor::TemplateInterface *ti=KTextEditor::templateInterface(doc);
|
|
|
|
ti->insertTemplateText(0,0,str,TQMap<TQString,TQString>());
|
|
|
|
} else {
|
|
|
|
doc->insertText( 0, 0, str );
|
|
|
|
view->setCursorPosition( line, col );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQWidget *KateFileTemplates::parentWindow()
|
|
|
|
{
|
|
|
|
return dynamic_cast<TQWidget*>(application()->activeMainWindow());
|
|
|
|
}
|
|
|
|
|
|
|
|
// The next part are tools to aid the creation and editing of templates
|
|
|
|
// /////////////////////////////////////////////////////////////////////
|
|
|
|
// Steps to produce a template
|
|
|
|
// * Choose a file to start from (optional)
|
|
|
|
// * Ask for a location to store the file -- suggesting either the file
|
|
|
|
// directory, or the local template directory.
|
|
|
|
// Set the URL
|
|
|
|
// * Get the template properties -- provide a dialog, which has filled in what
|
|
|
|
// we already know -- the author name, list of known groups
|
|
|
|
//
|
|
|
|
// Combine those data into the editor, and tell the user to position the cursor
|
|
|
|
// and edit the file as she wants to...
|
|
|
|
void KateFileTemplates::slotCreateTemplate()
|
|
|
|
{
|
|
|
|
KateTemplateWizard w( parentWindow(), this );
|
|
|
|
w.exec();
|
|
|
|
|
|
|
|
updateTemplateDirs();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tools for editing the existing templates
|
|
|
|
// Editing a template:
|
|
|
|
// * Select the template to edit
|
|
|
|
// * Open the template
|
|
|
|
// * Set the URL to a writable one if required
|
|
|
|
void KateFileTemplates::slotEditTemplate()
|
|
|
|
{
|
|
|
|
KDialogBase dlg( parentWindow(), "templatemanager", false, i18n("Manage File Templates"), KDialogBase::Close);
|
|
|
|
dlg.setMainWidget( new KateTemplateManager( this, &dlg ) );
|
|
|
|
dlg.exec();
|
|
|
|
}
|
|
|
|
//END KateFileTemplates
|
|
|
|
|
|
|
|
//BEGIN KateTemplateInfoWidget
|
|
|
|
// This widget can be used to change the data of a TemplateInfo object
|
|
|
|
KateTemplateInfoWidget::KateTemplateInfoWidget( TQWidget *parent, TemplateInfo *info, KateFileTemplates *kft )
|
|
|
|
: TQWidget( parent ),
|
|
|
|
info( info ),
|
|
|
|
kft( kft )
|
|
|
|
{
|
|
|
|
TQGridLayout *lo = new TQGridLayout( this, 6, 2 );
|
|
|
|
lo->setAutoAdd( true );
|
|
|
|
lo->setSpacing( KDialogBase::spacingHint() );
|
|
|
|
|
|
|
|
TQLabel *l = new TQLabel( i18n("&Template:"), this );
|
|
|
|
TQHBox *hb = new TQHBox( this );
|
|
|
|
hb->setSpacing( KDialogBase::spacingHint() );
|
|
|
|
leTemplate = new TQLineEdit( hb );
|
|
|
|
l->setBuddy( leTemplate );
|
|
|
|
TQWhatsThis::add( leTemplate, i18n("<p>This string is used as the template's name "
|
|
|
|
"and is displayed, for example, in the Template menu. It should describe the "
|
|
|
|
"meaning of the template, for example 'HTML Document'.</p>") );
|
|
|
|
ibIcon = new KIconButton( hb );
|
|
|
|
TQWhatsThis::add( ibIcon, i18n(
|
|
|
|
"Press to select or change the icon for this template") );
|
|
|
|
|
|
|
|
l = new TQLabel( i18n("&Group:"), this );
|
|
|
|
cmbGroup = new TQComboBox( true, this );
|
|
|
|
cmbGroup->insertStringList( kft->groups() );
|
|
|
|
l->setBuddy( cmbGroup );
|
|
|
|
TQWhatsThis::add( cmbGroup, i18n("<p>The group is used for chosing a "
|
|
|
|
"submenu for the plugin. If it is empty, 'Other' is used.</p>"
|
|
|
|
"<p>You can type any string to add a new group to your menu.</p>") );
|
|
|
|
|
|
|
|
l = new TQLabel( i18n("Document &name:"), this );
|
|
|
|
leDocumentName = new TQLineEdit( this );
|
|
|
|
l->setBuddy( leDocumentName );
|
|
|
|
TQWhatsThis::add( leDocumentName, i18n("<p>This string will be used to set a name "
|
|
|
|
"for the new document, to display in the title bar and file list.</p>"
|
|
|
|
"<p>If the string contains '%N', that will be replaced with a number "
|
|
|
|
"increasing with each similarly named file.</p><p> For example, if the "
|
|
|
|
"Document Name is 'New shellscript (%N).sh', the first document will be "
|
|
|
|
"named 'New shellscript (1).sh', the second 'New shellscipt (2).sh', and "
|
|
|
|
"so on.</p>") );
|
|
|
|
|
|
|
|
l = new TQLabel( i18n( "&Highlight:"), this );
|
|
|
|
btnHighlight = new TQPushButton( i18n("None"), this );
|
|
|
|
l->setBuddy( btnHighlight );
|
|
|
|
TQWhatsThis::add( btnHighlight, i18n("<p>Select the highlight to use for the "
|
|
|
|
"template. If 'None' is chosen, the property will not be set.</p>") );
|
|
|
|
|
|
|
|
l = new TQLabel( i18n("&Description:"), this );
|
|
|
|
leDescription = new TQLineEdit( this );
|
|
|
|
l->setBuddy( leDescription );
|
|
|
|
TQWhatsThis::add( leDescription, i18n("<p>This string is used, for example, as "
|
|
|
|
"context help for this template (such as the 'whatsthis' help for the "
|
|
|
|
"menu item.)</p>") );
|
|
|
|
|
|
|
|
l = new TQLabel( i18n("&Author:"), this );
|
|
|
|
leAuthor = new TQLineEdit( this );
|
|
|
|
l->setBuddy( leAuthor );
|
|
|
|
TQWhatsThis::add( leAuthor, i18n("<p>You can set this if you want to share your "
|
|
|
|
"template with other users.</p>"
|
|
|
|
"<p>the recommended form is like an Email "
|
|
|
|
"address: 'Anders Lund <anders@alweb.dk>'</p>") );
|
|
|
|
|
|
|
|
// if we have a object ! null
|
|
|
|
if ( info )
|
|
|
|
{
|
|
|
|
if ( ! info->icon.isEmpty() )
|
|
|
|
ibIcon->setIcon( info->icon );
|
|
|
|
leTemplate->setText( info->tmplate );
|
|
|
|
cmbGroup->setCurrentText( info->group );
|
|
|
|
leDescription->setText( info->description );
|
|
|
|
leAuthor->setText( info->author );
|
|
|
|
if ( ! info->highlight.isEmpty() )
|
|
|
|
btnHighlight->setText( info->highlight );
|
|
|
|
}
|
|
|
|
|
|
|
|
// fill in the Hl menu
|
|
|
|
Kate::Document *doc = kft->application()->documentManager()->activeDocument();
|
|
|
|
if ( doc )
|
|
|
|
{
|
|
|
|
TQPopupMenu *m = new TQPopupMenu( btnHighlight );
|
|
|
|
connect( m, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotHlSet( int ) ) );
|
|
|
|
TQDict<TQPopupMenu> submenus;
|
|
|
|
for ( uint n = 0; n < doc->hlModeCount(); n++ )
|
|
|
|
{
|
|
|
|
// create the sub menu if it does not exist
|
|
|
|
TQString text( doc->hlModeSectionName( n ) );
|
|
|
|
if ( ! text.isEmpty() )
|
|
|
|
{
|
|
|
|
if ( ! submenus[ text ] )
|
|
|
|
{
|
|
|
|
TQPopupMenu *sm = new TQPopupMenu();
|
|
|
|
submenus.insert( text, sm );
|
|
|
|
connect( sm, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotHlSet( int ) ) );
|
|
|
|
m->insertItem( text, sm );
|
|
|
|
}
|
|
|
|
|
|
|
|
// create the item
|
|
|
|
submenus[ text ]->insertItem( doc->hlModeName( n ), n );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m->insertItem( doc->hlModeName( n ), n );
|
|
|
|
}
|
|
|
|
|
|
|
|
btnHighlight->setPopup( m );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateTemplateInfoWidget::slotHlSet( int id )
|
|
|
|
{
|
|
|
|
btnHighlight->setText(
|
|
|
|
kft->application()->documentManager()->activeDocument()->hlModeName( id ) );
|
|
|
|
}
|
|
|
|
//END KateTemplateInfoWidget
|
|
|
|
|
|
|
|
//BEGIN KateTemplateWizard
|
|
|
|
// A simple wizard to help create a new template :-)
|
|
|
|
KateTemplateWizard::KateTemplateWizard( TQWidget *parent, KateFileTemplates *kft )
|
|
|
|
: KWizard( parent ),
|
|
|
|
kft( kft )
|
|
|
|
{
|
|
|
|
// Hide the help button for now
|
|
|
|
helpButton()->hide();
|
|
|
|
|
|
|
|
// 1) Optionally choose a file or existing template to start from
|
|
|
|
TQWidget *page = new TQWidget( this );
|
|
|
|
TQGridLayout *glo = new TQGridLayout( page );
|
|
|
|
//lo->setAutoAdd( true );
|
|
|
|
glo->setSpacing( KDialogBase::spacingHint() );
|
|
|
|
|
|
|
|
glo->addMultiCellWidget( new TQLabel( i18n("<p>If you want to base this "
|
|
|
|
"template on an existing file or template, select the appropriate option "
|
|
|
|
"below.</p>"), page ), 1, 1, 1, 2);
|
|
|
|
bgOrigin = new TQButtonGroup( page );
|
|
|
|
bgOrigin->hide();
|
|
|
|
bgOrigin->setRadioButtonExclusive( true );
|
|
|
|
|
|
|
|
TQRadioButton *rb = new TQRadioButton( i18n("Start with an &empty document" ), page );
|
|
|
|
bgOrigin->insert( rb, 1 );
|
|
|
|
glo->addMultiCellWidget( rb, 2, 2, 1, 2 );
|
|
|
|
rb->setChecked( true );
|
|
|
|
|
|
|
|
rb = new TQRadioButton( i18n("Use an existing file:"), page );
|
|
|
|
bgOrigin->insert( rb, 2 );
|
|
|
|
glo->addMultiCellWidget( rb, 3, 3, 1, 2 );
|
|
|
|
int marg = rb->style().subRect( TQStyle::SR_RadioButtonIndicator, rb ).width();
|
|
|
|
glo->addItem( new TQSpacerItem( marg, 1, TQSizePolicy::Fixed ), 4, 1 );
|
|
|
|
urOrigin = new KURLRequester( page );
|
|
|
|
glo->addWidget( urOrigin, 4, 2 );
|
|
|
|
|
|
|
|
rb = new TQRadioButton( i18n("Use an existing template:"), page );
|
|
|
|
bgOrigin->insert( rb, 3 );
|
|
|
|
glo->addMultiCellWidget( rb, 5, 5, 1, 2 );
|
|
|
|
glo->addItem( new TQSpacerItem( marg, 1, TQSizePolicy::Fixed ), 6, 1 );
|
|
|
|
btnTmpl = new TQPushButton( page );
|
|
|
|
glo->addWidget( btnTmpl, 6, 2 );
|
|
|
|
TQPopupMenu *m = new TQPopupMenu( btnTmpl );
|
|
|
|
connect( m, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotTmplateSet( int ) ) );
|
|
|
|
|
|
|
|
TQDict<TQPopupMenu> submenus;
|
|
|
|
for ( uint i = 0; i < kft->templates().count(); i++ )
|
|
|
|
{
|
|
|
|
if ( ! submenus[ kft->templates().at( i )->group ] )
|
|
|
|
{
|
|
|
|
TQPopupMenu *sm = new TQPopupMenu();
|
|
|
|
connect( sm, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotTmplateSet( int ) ) );
|
|
|
|
submenus.insert( kft->templates().at( i )->group, sm );
|
|
|
|
m->insertItem( kft->templates().at( i )->group, sm );
|
|
|
|
}
|
|
|
|
|
|
|
|
submenus[kft->templates().at( i )->group]->insertItem(
|
|
|
|
kft->templates().at( i )->tmplate, i );
|
|
|
|
}
|
|
|
|
btnTmpl->setPopup( m );
|
|
|
|
|
|
|
|
connect( bgOrigin, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(slotStateChanged(int)) );
|
|
|
|
connect( urOrigin, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotStateChanged(const TQString&)) );
|
|
|
|
|
|
|
|
glo->addMultiCell( new TQSpacerItem( 1, 1, TQSizePolicy::Expanding, TQSizePolicy::Expanding ), 7, 7, 1, 2 );
|
|
|
|
|
|
|
|
addPage( page, i18n("Choose Template Origin") );
|
|
|
|
kdDebug()<<"=== Adding template origin page at "<<page<<endl;
|
|
|
|
// 2) edit the template properties
|
|
|
|
kti = new KateTemplateInfoWidget( this, 0, kft );
|
|
|
|
kdDebug()<<"=== Adding template info page at "<<kti<<endl;
|
|
|
|
addPage( kti, i18n("Edit Template Properties") );
|
|
|
|
// get liekly values from KTE
|
|
|
|
TQMap<TQString, TQString> map;
|
|
|
|
map[ "fullname" ] = "";
|
|
|
|
map[ "email" ] = "";
|
|
|
|
|
|
|
|
KTextEditor::TemplateInterface::expandMacros( map, parent );
|
|
|
|
TQString sFullname = map["fullname"];
|
|
|
|
TQString sEmail = map["email"];
|
|
|
|
TQString _s = sFullname;
|
|
|
|
if ( ! sEmail.isEmpty() )
|
|
|
|
_s += " <" + sEmail + ">";
|
|
|
|
kti->leAuthor->setText( _s );
|
|
|
|
|
|
|
|
// 3) choose a location - either the template directory (default) or
|
|
|
|
// a custom location
|
|
|
|
page = new TQWidget( this );
|
|
|
|
glo = new TQGridLayout( page, 7, 2 );
|
|
|
|
glo->setSpacing( KDialogBase::spacingHint() );
|
|
|
|
|
|
|
|
glo->addMultiCellWidget( new TQLabel( i18n("<p>Choose a location for the "
|
|
|
|
"template. If you store it in the template directory, it will "
|
|
|
|
"automatically be added to the template menu.</p>"), page ), 1, 1, 1, 2);
|
|
|
|
|
|
|
|
bgLocation = new TQButtonGroup( page );
|
|
|
|
bgLocation->hide();
|
|
|
|
bgLocation->setRadioButtonExclusive( true );
|
|
|
|
|
|
|
|
rb = new TQRadioButton( i18n("Template directory"), page );
|
|
|
|
bgLocation->insert( rb, 1 );
|
|
|
|
glo->addMultiCellWidget( rb, 2, 2, 1, 2 );
|
|
|
|
rb->setChecked( true );
|
|
|
|
|
|
|
|
glo->addMultiCell( new TQSpacerItem( marg, 1, TQSizePolicy::Fixed ), 3, 4, 1, 1 );
|
|
|
|
leTemplateFileName = new TQLineEdit( page );
|
|
|
|
TQLabel *l = new TQLabel( leTemplateFileName, i18n("Template &file name:"), page );
|
|
|
|
|
|
|
|
glo->addWidget( l, 3, 2 );
|
|
|
|
glo->addWidget( leTemplateFileName, 4, 2 );
|
|
|
|
|
|
|
|
rb = new TQRadioButton( i18n("Custom location:"), page );
|
|
|
|
bgLocation->insert( rb, 2 );
|
|
|
|
glo->addMultiCellWidget( rb, 5, 5, 1, 2 );
|
|
|
|
|
|
|
|
glo->addItem( new TQSpacerItem( marg, 1, TQSizePolicy::Fixed ), 6, 1 );
|
|
|
|
urLocation = new KURLRequester( page );
|
|
|
|
glo->addWidget( urLocation, 6, 2 );
|
|
|
|
|
|
|
|
connect( bgLocation, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(slotStateChanged(int)) );
|
|
|
|
connect( urLocation, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotStateChanged(const TQString&)) );
|
|
|
|
connect( leTemplateFileName, TQT_SIGNAL(textChanged(const TQString &)), this, TQT_SLOT(slotStateChanged(const TQString &)) );
|
|
|
|
|
|
|
|
glo->addMultiCell( new TQSpacerItem( 1, 1, TQSizePolicy::Expanding, TQSizePolicy::Expanding ), 7, 7, 1, 2 );
|
|
|
|
|
|
|
|
addPage( page, i18n("Choose Location") );
|
|
|
|
kdDebug()<<"=== Adding location page at "<<page<<endl;
|
|
|
|
// 4) Should we edit the text to add some macros, replacing username etc?
|
|
|
|
// This is *only* relevant if the origin is a non-template file.
|
|
|
|
page = new TQWidget( this );
|
|
|
|
TQVBoxLayout *lo = new TQVBoxLayout( page );
|
|
|
|
lo->setSpacing( KDialogBase::spacingHint() );
|
|
|
|
|
|
|
|
lo->addWidget(
|
|
|
|
new TQLabel( i18n( "<p>You can replace certain strings in the text with "
|
|
|
|
"template macros.<p>If any of the data below is incorrect or missing, "
|
|
|
|
"edit the data in the TDE email information."), page ) );
|
|
|
|
|
|
|
|
cbRRealname = new TQCheckBox( i18n("Replace full name '%1' with the "
|
|
|
|
"'%{fullname}' macro").arg( sFullname ), page );
|
|
|
|
cbRRealname->setEnabled( ! sFullname.isEmpty() );
|
|
|
|
lo->addWidget( cbRRealname );
|
|
|
|
|
|
|
|
cbREmail = new TQCheckBox( i18n("Replace email address '%1' with the "
|
|
|
|
"'%email' macro").arg( sEmail ), page);
|
|
|
|
cbREmail->setEnabled( ! sEmail.isEmpty() );
|
|
|
|
lo->addWidget( cbREmail );
|
|
|
|
|
|
|
|
lo->addStretch();
|
|
|
|
|
|
|
|
addPage( page, i18n("Autoreplace Macros") );
|
|
|
|
kdDebug()<<"=== Adding autoreplace page at "<<page<<endl;
|
|
|
|
// 5) Display a summary
|
|
|
|
page = new TQWidget( this );
|
|
|
|
lo = new TQVBoxLayout( page );
|
|
|
|
lo->setSpacing( KDialogBase::spacingHint() );
|
|
|
|
|
|
|
|
TQString s = i18n("<p>The template will now be created and saved to the chosen "
|
|
|
|
"location. To position the cursor put a caret ('^') character where you "
|
|
|
|
"want it in files created from the template.</p>");
|
|
|
|
|
|
|
|
lo->addWidget( new TQLabel( s, page ) );
|
|
|
|
|
|
|
|
cbOpenTemplate = new TQCheckBox( i18n("Open the template for editing"), page );
|
|
|
|
|
|
|
|
lo->addWidget( cbOpenTemplate );
|
|
|
|
|
|
|
|
lo->addStretch();
|
|
|
|
|
|
|
|
addPage( page, i18n("Create Template") );
|
|
|
|
kdDebug()<<"=== Adding summary page at "<<endl;
|
|
|
|
connect( this, TQT_SIGNAL(selected(const TQString&)), this, TQT_SLOT(slotStateChanged(const TQString&)) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateTemplateWizard::slotTmplateSet( int idx )
|
|
|
|
{
|
|
|
|
btnTmpl->setText( kft->templates().at( idx )->tmplate );
|
|
|
|
selectedTemplateIdx = idx;
|
|
|
|
slotStateChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When the state of any button in any setup page is changed, set the
|
|
|
|
* enabled state of the next button accordingly.
|
|
|
|
*
|
|
|
|
* Origin:
|
|
|
|
* if file is chosen, the URLRequester must have a valid URL in it
|
|
|
|
* if template is chosen, one must be selected in the menu button.
|
|
|
|
*
|
|
|
|
* Props:
|
|
|
|
* anything goes, but if the user wants to store the template in the template
|
|
|
|
* directory, she should be encouraged to fill in information.
|
|
|
|
*/
|
|
|
|
void KateTemplateWizard::slotStateChanged()
|
|
|
|
{
|
|
|
|
bool sane( true );
|
|
|
|
switch ( indexOf( currentPage() ) )
|
|
|
|
{
|
|
|
|
case 0: // origin
|
|
|
|
{
|
|
|
|
int _t = bgOrigin->selectedId();
|
|
|
|
sane = ( _t == 1 ||
|
|
|
|
( _t == 2 && ! urOrigin->url().isEmpty() ) ||
|
|
|
|
( _t == 3 && ! btnTmpl->text().isEmpty() ) );
|
|
|
|
setAppropriate( page(3), _t == 2 );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1: // template properties
|
|
|
|
// if origin is a existing template, let us try setting some of the properties
|
|
|
|
if ( bgOrigin->selectedId() == 3 )
|
|
|
|
{
|
|
|
|
TemplateInfo *info = kft->templateInfo( selectedTemplateIdx );
|
|
|
|
kti->cmbGroup->setCurrentText( info->group );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2: // location
|
|
|
|
{
|
|
|
|
// If there is a template name, and the user did not enter text into
|
|
|
|
// the template file name entry, we will construct the name from the
|
|
|
|
// template name.
|
|
|
|
int _t = bgLocation->selectedId();
|
|
|
|
sane = ( ( _t == 1 && (! leTemplateFileName->text().isEmpty() || ! kti->leTemplate->text().isEmpty() ) ) ||
|
|
|
|
( _t == 2 && ! urLocation->url().isEmpty() ) );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4: // summary
|
|
|
|
setFinishEnabled( currentPage(), true );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nextButton()->setEnabled( sane );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This will create the new template based on the collected information.
|
|
|
|
*/
|
|
|
|
void KateTemplateWizard::accept()
|
|
|
|
{
|
|
|
|
// TODO check that everything is kosher, so that we can get a save location
|
|
|
|
// etc.
|
|
|
|
|
|
|
|
// check that we can combine a valid URL
|
|
|
|
KURL templateUrl;
|
|
|
|
if ( bgLocation->selectedId() == 1 )
|
|
|
|
{
|
|
|
|
TQString suggestion;
|
|
|
|
if ( ! leTemplateFileName->text().isEmpty() )
|
|
|
|
suggestion = leTemplateFileName->text();
|
|
|
|
else
|
|
|
|
suggestion = kti->leTemplate->text();
|
|
|
|
|
|
|
|
suggestion.replace(" ", "");
|
|
|
|
|
|
|
|
if ( ! suggestion.endsWith(".katetemplate") )
|
|
|
|
suggestion.append(".katetemplate");
|
|
|
|
|
|
|
|
TQString dir = TDEGlobal::dirs()->saveLocation( "data", "kate/plugins/katefiletemplates/templates/", true );
|
|
|
|
|
|
|
|
templateUrl = dir + suggestion;
|
|
|
|
|
|
|
|
if ( TQFile::exists( templateUrl.path() ) )
|
|
|
|
{
|
|
|
|
if ( KMessageBox::warningContinueCancel( this, i18n(
|
|
|
|
"<p>The file <br><strong>'%1'</strong><br> already exists; if you "
|
|
|
|
"do not want to overwrite it, change the template file name to "
|
|
|
|
"something else.").arg( templateUrl.prettyURL() ),
|
|
|
|
i18n("File Exists"), i18n("Overwrite") )
|
|
|
|
== KMessageBox::Cancel )
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
templateUrl = urLocation->url();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQWizard::accept();
|
|
|
|
// The following must be done:
|
|
|
|
// 1) add the collected template information to the top
|
|
|
|
uint ln = 0;
|
|
|
|
TQString s, str;
|
|
|
|
if ( ! kti->leTemplate->text().isEmpty() )
|
|
|
|
s += " Template=" + kti->leTemplate->text();
|
|
|
|
if ( ! kti->cmbGroup->currentText().isEmpty() )
|
|
|
|
s += " Group=" + kti->cmbGroup->currentText();
|
|
|
|
if ( ! kti->leDocumentName->text().isEmpty() )
|
|
|
|
s += " Documentname=" + kti->leDocumentName->text();
|
|
|
|
if ( ! kti->ibIcon->icon().isEmpty() )
|
|
|
|
s += " Icon=" + kti->ibIcon->icon();
|
|
|
|
if ( ! kti->btnHighlight->text().isEmpty() )
|
|
|
|
s += " Highlight=" + kti->btnHighlight->text();
|
|
|
|
|
|
|
|
str = "katetemplate:" + s;
|
|
|
|
|
|
|
|
if ( ! (s = kti->leAuthor->text()).isEmpty() )
|
|
|
|
str += "\nkatetemplate: Author=" + s;
|
|
|
|
|
|
|
|
if ( ! (s = kti->leDescription->text()).isEmpty() )
|
|
|
|
str += "\nkatetemplate: Description=" + s;
|
|
|
|
|
|
|
|
// 2) If a file or template is chosen, open that. and fill the data into a string
|
|
|
|
int toid = bgOrigin->selectedId(); // 1 = blank, 2 = file, 3 = template
|
|
|
|
kdDebug()<<"=== create template: origin type "<<toid<<endl;
|
|
|
|
if ( toid > 1 )
|
|
|
|
{
|
|
|
|
KURL u;
|
|
|
|
if ( toid == 2 ) // file
|
|
|
|
u = KURL( urOrigin->url() );
|
|
|
|
else // template
|
|
|
|
u = KURL( kft->templates().at( selectedTemplateIdx )->filename );
|
|
|
|
|
|
|
|
TQString tmpfile, tmp;
|
|
|
|
if ( TDEIO::NetAccess::download( u, tmpfile, 0L ) )
|
|
|
|
{
|
|
|
|
TQFile file(tmpfile);
|
|
|
|
if ( ! file.open( IO_ReadOnly ) )
|
|
|
|
{
|
|
|
|
KMessageBox::sorry( this, i18n(
|
|
|
|
"<qt>Error opening the file<br><strong>%1</strong><br>for reading. "
|
|
|
|
"The document will not be created</qt>").arg(u.prettyURL()),
|
|
|
|
i18n("Template Plugin"), 0 );
|
|
|
|
|
|
|
|
TDEIO::NetAccess::removeTempFile( tmpfile );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
TQString ln;
|
|
|
|
bool trymore = true;
|
|
|
|
while ( !stream.eof() )
|
|
|
|
{
|
|
|
|
// skip template headers
|
|
|
|
ln = stream.readLine();
|
|
|
|
if ( trymore && ln.startsWith("katetemplate:") )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
trymore = false;
|
|
|
|
tmp += "\n" + ln;
|
|
|
|
}
|
|
|
|
|
|
|
|
file.close();
|
|
|
|
TDEIO::NetAccess::removeTempFile( tmpfile );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( toid == 2 ) // file
|
|
|
|
{
|
|
|
|
// 3) if the file is not already a template, escape any "%" and "^" in it,
|
|
|
|
// and try do do some replacement of the authors username, name and email.
|
|
|
|
tmp.replace( TQRegExp("%(?=\\{[^}]+\\})"), "\\%" );
|
|
|
|
tmp.replace( TQRegExp("\\$(?=\\{[^}]+\\})"), "\\$" );
|
|
|
|
//tmp.replace( "^", "\\^" );
|
|
|
|
|
|
|
|
if ( cbRRealname->isChecked() && ! sFullname.isEmpty() )
|
|
|
|
tmp.replace( sFullname, "%{realname}" );
|
|
|
|
|
|
|
|
|
|
|
|
if ( cbREmail->isChecked() && ! sEmail.isEmpty() )
|
|
|
|
tmp.replace( sEmail, "%{email}" );
|
|
|
|
}
|
|
|
|
|
|
|
|
str += tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 4) Save the document to the suggested URL if possible
|
|
|
|
|
|
|
|
bool succes = false;
|
|
|
|
|
|
|
|
if ( templateUrl.isValid() )
|
|
|
|
{
|
|
|
|
if ( templateUrl.isLocalFile() )
|
|
|
|
{
|
|
|
|
TQFile file( templateUrl.path() );
|
|
|
|
if ( file.open(IO_WriteOnly) )
|
|
|
|
{
|
|
|
|
kdDebug()<<"file opened with succes"<<endl;
|
|
|
|
TQTextStream stream( &file );
|
|
|
|
stream << str;
|
|
|
|
file.close();
|
|
|
|
succes = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KTempFile tmp;
|
|
|
|
TQString fn = tmp.name();
|
|
|
|
TQTextStream stream( tmp.file() );
|
|
|
|
stream << str;
|
|
|
|
tmp.close();
|
|
|
|
|
|
|
|
succes = TDEIO::NetAccess::upload( fn, templateUrl, 0 );
|
|
|
|
TDEIO::NetAccess::removeTempFile( fn );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ! succes )
|
|
|
|
{
|
|
|
|
KMessageBox::sorry( this, i18n(
|
|
|
|
"Unable to save the template to '%1'.\n\nThe template will be opened, "
|
|
|
|
"so you can save it from the editor.").arg( templateUrl.prettyURL() ),
|
|
|
|
i18n("Save Failed") );
|
|
|
|
|
|
|
|
kft->application()->activeMainWindow()->viewManager()->openURL( KURL() );
|
|
|
|
Kate::View *view = kft->application()->activeMainWindow()->viewManager()->activeView();
|
|
|
|
Kate::Document *doc = view->getDoc();
|
|
|
|
doc->insertText( ln++, 0, str );
|
|
|
|
}
|
|
|
|
else if ( cbOpenTemplate->isChecked() )
|
|
|
|
kft->application()->activeMainWindow()->viewManager()->openURL( templateUrl );
|
|
|
|
}
|
|
|
|
//END KateTemplateWizard
|
|
|
|
|
|
|
|
//BEGIN KateTemplateItem
|
|
|
|
class KateTemplateItem : public KListViewItem
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
KateTemplateItem( KListViewItem *parent, TemplateInfo *templateinfo )
|
|
|
|
: KListViewItem( parent, templateinfo->tmplate ), templateinfo( templateinfo )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
TemplateInfo *templateinfo;
|
|
|
|
};
|
|
|
|
//END KateTemplateItem
|
|
|
|
|
|
|
|
//BEGIN KFTNewStuff
|
|
|
|
class KFTNewStuff : public KNewStuff {
|
|
|
|
public:
|
|
|
|
KFTNewStuff( const TQString &type, TQWidget *parent=0 ) : KNewStuff( type, parent ), m_win( parent ) {}
|
|
|
|
~KFTNewStuff() {}
|
|
|
|
bool install( const TQString &/*filename*/ ) { return true; }
|
|
|
|
bool createUploadFile( const TQString &/*filename*/ ) { return false; }
|
|
|
|
TQString downloadDestination( KNS::Entry *entry )
|
|
|
|
{
|
|
|
|
TQString dir = TDEGlobal::dirs()->saveLocation( "data", "kate/plugins/katefiletemplates/templates/", true );
|
|
|
|
return dir.append( entry->payload().filename() );
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
TQWidget *m_win;
|
|
|
|
};
|
|
|
|
//END KTNewStuff
|
|
|
|
|
|
|
|
//BEGIN KateTemplateManager
|
|
|
|
KateTemplateManager::KateTemplateManager( KateFileTemplates *kft, TQWidget *parent, const char *name )
|
|
|
|
: TQWidget( parent, name )
|
|
|
|
, kft( kft )
|
|
|
|
{
|
|
|
|
TQGridLayout *lo = new TQGridLayout( this, 2, 6 );
|
|
|
|
lo->setSpacing( KDialogBase::spacingHint() );
|
|
|
|
lvTemplates = new KListView( this );
|
|
|
|
lvTemplates->addColumn( i18n("Template") );
|
|
|
|
lo->addMultiCellWidget( lvTemplates, 1, 1, 1, 6 );
|
|
|
|
connect( lvTemplates, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotUpdateState()) );
|
|
|
|
|
|
|
|
btnNew = new TQPushButton( i18n("New..."), this );
|
|
|
|
connect( btnNew, TQT_SIGNAL(clicked()), kft, TQT_SLOT(slotCreateTemplate()) );
|
|
|
|
lo->addWidget( btnNew, 2, 2 );
|
|
|
|
|
|
|
|
btnEdit = new TQPushButton( i18n("Edit..."), this );
|
|
|
|
connect( btnEdit, TQT_SIGNAL(clicked()), this, TQT_SLOT( slotEditTemplate()) );
|
|
|
|
lo->addWidget( btnEdit, 2, 3 );
|
|
|
|
|
|
|
|
btnRemove = new TQPushButton( i18n("Remove"), this );
|
|
|
|
connect( btnRemove, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotRemoveTemplate()) );
|
|
|
|
lo->addWidget( btnRemove, 2, 4 );
|
|
|
|
|
|
|
|
btnUpload = new TQPushButton( i18n("Upload..."), this );
|
|
|
|
connect( btnUpload, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotUpload()) );
|
|
|
|
lo->addWidget( btnUpload, 2, 5 );
|
|
|
|
|
|
|
|
btnDownload = new TQPushButton( i18n("Download..."), this );
|
|
|
|
connect( btnDownload, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotDownload()) );
|
|
|
|
lo->addWidget( btnDownload, 2, 6 );
|
|
|
|
|
|
|
|
lo->setColStretch( 1, 1 );
|
|
|
|
|
|
|
|
reload();
|
|
|
|
slotUpdateState();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateTemplateManager::apply()
|
|
|
|
{
|
|
|
|
// if any files were removed, delete them unless they are not writeable, in
|
|
|
|
// which case a link .filename should be put in the writable directory.
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateTemplateManager::reload()
|
|
|
|
{
|
|
|
|
lvTemplates->clear();
|
|
|
|
|
|
|
|
TQDict<KListViewItem> groupitems; // FIXME TQMAP
|
|
|
|
for ( uint i = 0; i < kft->templates().count(); i++ )
|
|
|
|
{
|
|
|
|
if ( ! groupitems[ kft->templates().at( i )->group ] )
|
|
|
|
{
|
|
|
|
groupitems.insert( kft->templates().at( i )->group , new KListViewItem( lvTemplates, kft->templates().at( i )->group ) );
|
|
|
|
groupitems[ kft->templates().at( i )->group ]->setOpen( true );
|
|
|
|
}
|
|
|
|
new KateTemplateItem( groupitems[ kft->templates().at( i )->group ], kft->templates().at( i ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateTemplateManager::slotUpdateState()
|
|
|
|
{
|
|
|
|
// enable/disable buttons wrt the current item in the list view.
|
|
|
|
// we are in single selection mode, so currentItem() is selected.
|
|
|
|
bool cool = false;
|
|
|
|
if ( dynamic_cast<KateTemplateItem*>( lvTemplates->currentItem() ) )
|
|
|
|
cool = true;
|
|
|
|
|
|
|
|
btnEdit->setEnabled( cool );
|
|
|
|
btnRemove->setEnabled( cool );
|
|
|
|
btnUpload->setEnabled( cool );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateTemplateManager::slotEditTemplate()
|
|
|
|
{
|
|
|
|
// open the template file in kate
|
|
|
|
// TODO show the properties dialog, and modify the file if the data was changed.
|
|
|
|
KateTemplateItem *item = dynamic_cast<KateTemplateItem*>( lvTemplates->currentItem() );
|
|
|
|
if ( item )
|
|
|
|
kft->application()->activeMainWindow()->viewManager()->openURL( item->templateinfo->filename );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KateTemplateManager::slotRemoveTemplate()
|
|
|
|
{
|
|
|
|
KateTemplateItem *item = dynamic_cast<KateTemplateItem*>( lvTemplates->currentItem() );
|
|
|
|
if ( item )
|
|
|
|
{
|
|
|
|
// Find all instances of filename, and try to delete them.
|
|
|
|
// If it fails (there was a global, unwritable instance), add to a
|
|
|
|
// list of removed templates
|
|
|
|
TDEConfig *config = kapp->config();
|
|
|
|
TQString fname = item->templateinfo->filename.section( '/', -1 );
|
|
|
|
TQStringList templates = TDEGlobal::dirs()->findAllResources(
|
|
|
|
"data", fname.prepend( "kate/plugins/katefiletemplates/templates/" ),
|
|
|
|
false,true);
|
|
|
|
int failed = 0;
|
|
|
|
int removed = 0;
|
|
|
|
for ( TQStringList::Iterator it=templates.begin(); it!=templates.end(); ++it )
|
|
|
|
{
|
|
|
|
if ( ! TQFile::remove(*it) )
|
|
|
|
failed++;
|
|
|
|
else
|
|
|
|
removed++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( failed )
|
|
|
|
{
|
|
|
|
config->setGroup( "KateFileTemplates" );
|
|
|
|
TQStringList l;
|
|
|
|
config->readListEntry( "Hidden", l, ';' );
|
|
|
|
l << fname;
|
|
|
|
config->writeEntry( "Hidden", l, ';' );
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we removed any files, we should delete a KNewStuff key
|
|
|
|
// for this template, so the template is installable again.
|
|
|
|
// ### This assumes that the knewstuff name is similar to the template name.
|
|
|
|
kdDebug()<<"trying to remove knewstuff key '"<<item->templateinfo->tmplate<<"'"<<endl;
|
|
|
|
config->setGroup("KNewStuffStatus");
|
|
|
|
config->deleteEntry( item->templateinfo->tmplate );
|
|
|
|
|
|
|
|
|
|
|
|
kft->updateTemplateDirs();
|
|
|
|
reload();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// KNewStuff upload
|
|
|
|
void KateTemplateManager::slotUpload()
|
|
|
|
{
|
|
|
|
// TODO something nicer, like preparing the meta data from the template info.
|
|
|
|
KateTemplateItem *item = dynamic_cast<KateTemplateItem*>( lvTemplates->currentItem() );
|
|
|
|
if ( item )
|
|
|
|
{
|
|
|
|
KFTNewStuff *ns = new KFTNewStuff( "katefiletemplates/template", this );
|
|
|
|
ns->upload( item->templateinfo->filename, TQString() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// KNewStuff download
|
|
|
|
void KateTemplateManager::slotDownload()
|
|
|
|
{
|
|
|
|
KFTNewStuff *ns = new KFTNewStuff( "katefiletemplates/template", this );
|
|
|
|
ns->download();
|
|
|
|
|
|
|
|
kft->updateTemplateDirs();
|
|
|
|
reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
//END KateTemplateManager
|
|
|
|
|
|
|
|
// kate: space-indent on; indent-width 2; replace-tabs on;
|
|
|
|
|
|
|
|
#include "filetemplates.moc"
|