KoTemplateCreateDia.cpp
1/*
2 This file is part of the KDE project
3 Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
4 2000 Werner Trobin <trobin@kde.org>
5 Copyright (C) 2004 Nicolas GOUTTE <goutte@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21*/
22
23#include <KoTemplateCreateDia.h>
24
25#include <tqfile.h>
26#include <tqlayout.h>
27#include <tqlabel.h>
28#include <tqgroupbox.h>
29#include <tqradiobutton.h>
30#include <tqpushbutton.h>
31#include <tqheader.h>
32#include <tqcheckbox.h>
33#include <tqtooltip.h>
34
35#include <tdetempfile.h>
36#include <klineedit.h>
37#include <tdelistview.h>
38#include <tdelocale.h>
39#include <KoTemplates.h>
40#include <kicondialog.h>
41#include <kinputdialog.h>
42#include <tdemessagebox.h>
43#include <kimageio.h>
44#include <kstandarddirs.h>
45#include <kdebug.h>
46#include <tdeio/netaccess.h>
47#include <kiconloader.h>
48#include <tdeaboutdata.h>
49#include <tdeconfigbase.h>
50#include <tdeconfig.h>
51
52#include <stdlib.h>
53#include <tdeinstance.h>
54
55
56class KoTemplateCreateDiaPrivate {
57public:
58 KoTemplateCreateDiaPrivate( TQWidget* /*parent*/, TDEInstance * instance)
59 : m_instance( instance ), m_tempFile( TQString(), ".png" )
60 {
61 m_tree=0L;
62 m_name=0L;
63 m_default=0L;
64 m_custom=0L;
65 m_select=0L;
66 m_preview=0L;
67 m_groups=0L;
68 m_add=0L;
69 m_remove=0L;
70 m_defaultTemplate=0L;
71 m_tempFile.setAutoDelete( true );
72 }
73 ~KoTemplateCreateDiaPrivate() {
74 delete m_tree;
75 }
76
77 KoTemplateTree *m_tree;
78 KLineEdit *m_name;
79 TQRadioButton *m_default, *m_custom;
80 TQPushButton *m_select;
81 TQLabel *m_preview;
82 TQString m_customFile;
83 TQPixmap m_customPixmap;
84 TDEListView *m_groups;
85 TQPushButton *m_add, *m_remove;
86 TQCheckBox *m_defaultTemplate;
87 TDEInstance *m_instance;
88 bool m_changed;
90 KTempFile m_tempFile;
91};
92
93
94/****************************************************************************
95 *
96 * Class: koTemplateCreateDia
97 *
98 ****************************************************************************/
99
100KoTemplateCreateDia::KoTemplateCreateDia( const TQCString &templateType, TDEInstance *instance,
101 const TQString &file, const TQPixmap &pix, TQWidget *parent ) :
102 KDialogBase( parent, "template create dia", true, i18n( "Create Template" ),
103 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ), m_file(file), m_pixmap(pix) {
104
105 d=new KoTemplateCreateDiaPrivate( parent, instance );
106
107 TQFrame *mainwidget=makeMainWidget();
108 TQHBoxLayout *mbox=new TQHBoxLayout(mainwidget, 0, KDialogBase::spacingHint());
109 TQVBoxLayout *leftbox=new TQVBoxLayout(mbox);
110
111 TQLabel *label=new TQLabel(i18n("Name:"), mainwidget);
112 leftbox->addSpacing(label->fontMetrics().height()/2);
113 TQHBoxLayout *namefield=new TQHBoxLayout(leftbox);
114 namefield->addWidget(label);
115 d->m_name=new KLineEdit(mainwidget);
116 d->m_name->setFocus();
117 connect(d->m_name, TQ_SIGNAL(textChanged(const TQString &)),
118 this, TQ_SLOT(slotNameChanged(const TQString &)));
119 namefield->addWidget(d->m_name);
120
121 label=new TQLabel(i18n("Group:"), mainwidget);
122 leftbox->addWidget(label);
123 d->m_groups=new TDEListView(mainwidget);
124 leftbox->addWidget(d->m_groups);
125 d->m_groups->addColumn("");
126 d->m_groups->header()->hide();
127 d->m_groups->setRootIsDecorated(true);
128 d->m_groups->setSorting(0);
129
130 d->m_tree=new KoTemplateTree(templateType, instance, true);
131 fillGroupTree();
132 d->m_groups->sort();
133
134 TQHBoxLayout *bbox=new TQHBoxLayout(leftbox);
135 d->m_add=new TQPushButton(i18n("&Add Group..."), mainwidget);
136 connect(d->m_add, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotAddGroup()));
137 bbox->addWidget(d->m_add);
138 d->m_remove=new TQPushButton(i18n("&Remove"), mainwidget);
139 connect(d->m_remove, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotRemove()));
140 bbox->addWidget(d->m_remove);
141
142 TQVBoxLayout *rightbox=new TQVBoxLayout(mbox);
143 TQGroupBox *pixbox=new TQGroupBox(i18n("Picture"), mainwidget);
144 rightbox->addWidget(pixbox);
145 TQVBoxLayout *pixlayout=new TQVBoxLayout(pixbox, KDialogBase::marginHint(),
147 pixlayout->addSpacing(pixbox->fontMetrics().height()/2);
148 pixlayout->addStretch(1);
149 d->m_default=new TQRadioButton(i18n("&Default"), pixbox);
150 d->m_default->setChecked(true);
151 connect(d->m_default, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotDefault()));
152 pixlayout->addWidget(d->m_default);
153 TQHBoxLayout *custombox=new TQHBoxLayout(pixlayout);
154 d->m_custom=new TQRadioButton(i18n("Custom"), pixbox);
155 d->m_custom->setChecked(false);
156 connect(d->m_custom, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotCustom()));
157 custombox->addWidget(d->m_custom);
158 d->m_select=new TQPushButton(i18n("&Select..."), pixbox);
159 connect(d->m_select, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotSelect()));
160 custombox->addWidget(d->m_select, 1);
161 custombox->addStretch(1);
162 pixlayout->addStretch(1);
163 label=new TQLabel(i18n("Preview:"), pixbox);
164 pixlayout->addWidget(label);
165 TQHBoxLayout *previewbox=new TQHBoxLayout(pixlayout);
166 previewbox->addStretch(10);
167 d->m_preview=new TQLabel(pixbox); // setPixmap() -> auto resize?
168 previewbox->addWidget(d->m_preview);
169 previewbox->addStretch(10);
170 pixlayout->addStretch(8);
171
172 d->m_defaultTemplate = new TQCheckBox( i18n("Use the new template as default"), mainwidget );
173 d->m_defaultTemplate->setChecked( true );
174 TQToolTip::add( d->m_defaultTemplate, i18n("Use the new template every time %1 starts").arg(instance->aboutData()->programName() ) );
175 rightbox->addWidget( d->m_defaultTemplate );
176
177 enableButtonOK(false);
178 d->m_changed=false;
179 updatePixmap();
180
181 connect(d->m_groups,TQ_SIGNAL( selectionChanged()),this,TQ_SLOT(slotSelectionChanged()));
182
183 d->m_remove->setEnabled(d->m_groups->currentItem());
184}
185
186KoTemplateCreateDia::~KoTemplateCreateDia() {
187 delete d;
188}
189
190void KoTemplateCreateDia::slotSelectionChanged()
191{
192 const TQListViewItem* item = d->m_groups->currentItem();
193 d->m_remove->setEnabled( item );
194 if ( ! item )
195 return;
196
197 if ( item->depth() > 0 )
198 {
199 d->m_name->setText( item->text( 0 ) );
200 }
201}
202
203void KoTemplateCreateDia::createTemplate( const TQCString &templateType, TDEInstance *instance,
204 const TQString &file, const TQPixmap &pix, TQWidget *parent ) {
205
206 KoTemplateCreateDia *dia = new KoTemplateCreateDia( templateType, instance, file, pix, parent );
207 dia->exec();
208 delete dia;
209}
210
211void KoTemplateCreateDia::slotOk() {
212
213 // get the current item, if there is one...
214 TQListViewItem *item=d->m_groups->currentItem();
215 if(!item)
216 item=d->m_groups->firstChild();
217 if(!item) { // safe :)
218 d->m_tree->writeTemplateTree();
220 return;
221 }
222 // is it a group or a template? anyway - get the group :)
223 if(item->depth()!=0)
224 item=item->parent();
225 if(!item) { // *very* safe :P
226 d->m_tree->writeTemplateTree();
228 return;
229 }
230
231 KoTemplateGroup *group=d->m_tree->find(item->text(0));
232 if(!group) { // even safer
233 d->m_tree->writeTemplateTree();
235 return;
236 }
237
238 if(d->m_name->text().isEmpty()) {
239 d->m_tree->writeTemplateTree();
241 return;
242 }
243
244 // copy the tmp file and the picture the app provides
245 TQString dir=d->m_tree->instance()->dirs()->saveLocation(d->m_tree->templateType());
246 dir+=group->name();
247 TQString templateDir=dir+"/.source/";
248 TQString iconDir=dir+"/.icon/";
249
250 TQString file=KoTemplates::stripWhiteSpace(d->m_name->text());
251 TQString tmpIcon=".icon/"+file;
252 tmpIcon+=".png";
253 TQString icon=iconDir+file;
254 icon+=".png";
255
256 // try to find the extension for the template file :P
257 const int pos = m_file.findRev( '.' );
258 TQString ext;
259 if ( pos > -1 )
260 ext = m_file.mid( pos );
261 else
262 kdWarning(30004) << "Template extension not found!" << endl;
263
264 KURL dest;
265 dest.setPath(templateDir+file+ext);
266 if ( TQFile::exists( dest.prettyURL(0, KURL::StripFileProtocol) ) )
267 {
268 do
269 {
270 file.prepend( '_' );
271 dest.setPath( templateDir + file + ext );
272 tmpIcon=".icon/"+file+".png";
273 icon=iconDir+file+".png";
274 }
275 while ( TDEIO::NetAccess::exists( dest, true, this ) );
276 }
277 bool ignore = false;
278 kdDebug(30004) << "Trying to create template: " << d->m_name->text() << "URL=" << ".source/"+file+ext << " ICON=" << tmpIcon << endl;
279 KoTemplate *t=new KoTemplate(d->m_name->text(), TQString(), ".source/"+file+ext, tmpIcon, "", "", false, true);
280 if(!group->add(t)) {
281 KoTemplate *existingTemplate=group->find(d->m_name->text());
282 if(existingTemplate && !existingTemplate->isHidden()) {
283 if(KMessageBox::warningYesNo(this, i18n("Do you really want to overwrite"
284 " the existing '%1' template?").
285 arg(existingTemplate->name()))==KMessageBox::Yes)
286 group->add(t, true);
287 else
288 {
289 delete t;
290 return;
291 }
292 }
293 else
294 ignore = true;
295 }
296
297 if(!TDEStandardDirs::makeDir(templateDir) || !TDEStandardDirs::makeDir(iconDir)) {
298 d->m_tree->writeTemplateTree();
300 return;
301 }
302
303 KURL orig;
304 orig.setPath( m_file );
305 // don't overwrite the hidden template file with a new non-hidden one
306 if ( !ignore )
307 {
308 // copy the template file
309 TDEIO::NetAccess::file_copy( orig, dest, -1, true, false, this );
310
311 // save the picture
312 if(d->m_default->isChecked() && !m_pixmap.isNull())
313 m_pixmap.save(icon, "PNG");
314 else if(!d->m_customPixmap.isNull())
315 d->m_customPixmap.save(icon, "PNG");
316 else
317 kdWarning(30004) << "Could not save the preview picture!" << endl;
318 }
319
320 // if there's a .directory file, we copy this one, too
321 bool ready=false;
322 TQStringList tmp=group->dirs();
323 for(TQStringList::ConstIterator it=tmp.begin(); it!=tmp.end() && !ready; ++it) {
324 if((*it).contains(dir)==0) {
325 orig.setPath( (*it)+".directory" );
326 // Check if we can read the file
327 if( TDEIO::NetAccess::exists(orig, true, this) ) {
328 dest.setPath( dir+"/.directory" );
329 // We copy the file with overwrite
330 TDEIO::NetAccess::file_copy( orig, dest, -1, true, false, this );
331 ready=true;
332 }
333 }
334 }
335
336 d->m_tree->writeTemplateTree();
337
338 if ( d->m_defaultTemplate->isChecked() )
339 {
340 TDEConfigGroup grp( d->m_instance->config(), "TemplateChooserDialog" );
341 grp.writeEntry( "LastReturnType", "Template" );
342 grp.writePathEntry( "FullTemplateName", dir + "/" + t->file() );
343 grp.writePathEntry( "AlwaysUseTemplate", dir + "/" + t->file() );
344 }
346}
347
348void KoTemplateCreateDia::slotDefault() {
349
350 d->m_default->setChecked(true);
351 d->m_custom->setChecked(false);
352 updatePixmap();
353}
354
355void KoTemplateCreateDia::slotCustom() {
356
357 d->m_default->setChecked(false);
358 d->m_custom->setChecked(true);
359 if(d->m_customFile.isEmpty())
360 slotSelect();
361 else
362 updatePixmap();
363}
364
365void KoTemplateCreateDia::slotSelect() {
366
367 d->m_default->setChecked(false);
368 d->m_custom->setChecked(true);
369
370 TQString name = TDEIconDialog::getIcon();
371 if( name.isEmpty() ) {
372 if(d->m_customFile.isEmpty()) {
373 d->m_default->setChecked(true);
374 d->m_custom->setChecked(false);
375 }
376 return;
377 }
378 // ### TODO: do a better remote loading without having to have d->m_tempFile
379 TQString path = TDEGlobal::iconLoader()->iconPath(name, TDEIcon::Desktop);
380 d->m_customFile = path;
381 d->m_customPixmap=TQPixmap();
382 updatePixmap();
383}
384
385void KoTemplateCreateDia::slotNameChanged(const TQString &name) {
386
387 if( ( name.stripWhiteSpace().isEmpty() || !d->m_groups->firstChild() ) && !d->m_changed )
388 enableButtonOK(false);
389 else
390 enableButtonOK(true);
391}
392
393void KoTemplateCreateDia::slotAddGroup() {
394 bool ok=false;
395 const TQString name ( KInputDialog::getText( i18n("Add Group"), i18n("Enter group name:"), TQString(), &ok, this ) );
396 if(!ok)
397 return;
398 KoTemplateGroup *group=d->m_tree->find(name);
399 if(group && !group->isHidden())
400 {
401 KMessageBox::information( this, i18n("This name is already used."), i18n("Add Group") );
402 return;
403 }
404 TQString dir=d->m_tree->instance()->dirs()->saveLocation(d->m_tree->templateType());
405 dir+=name;
406 KoTemplateGroup *newGroup=new KoTemplateGroup(name, dir, 0, true);
407 d->m_tree->add(newGroup);
408 TQListViewItem *item=new TQListViewItem(d->m_groups, name);
409 d->m_groups->setCurrentItem(item);
410 d->m_groups->sort();
411 d->m_name->setFocus();
412 enableButtonOK(true);
413 d->m_changed=true;
414}
415
416void KoTemplateCreateDia::slotRemove() {
417
418 TQListViewItem *item=d->m_groups->currentItem();
419 if(!item)
420 return;
421
422 TQString what;
423 TQString removed;
424 if (item->depth()==0) {
425 what = i18n("Do you really want to remove that group?");
426 removed = i18n("Remove Group");
427 } else {
428 what = i18n("Do you really want to remove that template?");
429 removed = i18n("Remove Template");
430 }
431
433 removed,KGuiItem(i18n("&Delete"),"edit-delete"))==KMessageBox::Cancel) {
434 d->m_name->setFocus();
435 return;
436 }
437
438 if(item->depth()==0) {
439 KoTemplateGroup *group=d->m_tree->find(item->text(0));
440 if(group)
441 group->setHidden(true);
442 }
443 else {
444 bool done=false;
445 for(KoTemplateGroup *g=d->m_tree->first(); g!=0L && !done; g=d->m_tree->next()) {
446 KoTemplate *t=g->find(item->text(0));
447 if(t) {
448 t->setHidden(true);
449 done=true;
450 }
451 }
452 }
453 delete item;
454 item=0L;
455 enableButtonOK(true);
456 d->m_name->setFocus();
457 d->m_changed=true;
458}
459
460void KoTemplateCreateDia::updatePixmap() {
461
462 if(d->m_default->isChecked() && !m_pixmap.isNull())
463 d->m_preview->setPixmap(m_pixmap);
464 else if(d->m_custom->isChecked() && !d->m_customFile.isEmpty()) {
465 if(d->m_customPixmap.isNull()) {
466 kdDebug(30004) << "Trying to load picture " << d->m_customFile << endl;
467 // use the code in KoTemplate to load the image... hacky, I know :)
468 KoTemplate t("foo", "bar", TQString(), d->m_customFile);
469 d->m_customPixmap=t.loadPicture(d->m_tree->instance());
470 }
471 else
472 kdWarning(30004) << "Trying to load picture" << endl;
473
474 if(!d->m_customPixmap.isNull())
475 d->m_preview->setPixmap(d->m_customPixmap);
476 else
477 d->m_preview->setText(i18n("Could not load picture."));
478 }
479 else
480 d->m_preview->setText(i18n("No picture available."));
481}
482
483void KoTemplateCreateDia::fillGroupTree() {
484
485 for(KoTemplateGroup *group=d->m_tree->first(); group!=0L; group=d->m_tree->next()) {
486 if(group->isHidden())
487 continue;
488 TQListViewItem *groupItem=new TQListViewItem(d->m_groups, group->name());
489 for(KoTemplate *t=group->first(); t!=0L; t=group->next()) {
490 if(t->isHidden())
491 continue;
492 (void)new TQListViewItem(groupItem, t->name());
493 }
494 }
495}
496
497#include <KoTemplateCreateDia.moc>
virtual void slotCancel()
virtual void slotOk()
static int marginHint()
static int spacingHint()
static TQString getText(const TQString &caption, const TQString &label, const TQString &value=TQString::null, bool *ok=0, TQWidget *parent=0, const char *name=0, TQValidator *validator=0, const TQString &mask=TQString::null)
static void information(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const TQString &dontShowAgainName=TQString::null, int options=Notify)
static int warningYesNo(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const KGuiItem &buttonYes=KStdGuiItem::yes(), const KGuiItem &buttonNo=KStdGuiItem::no(), const TQString &dontAskAgainName=TQString::null, int options=Notify|Dangerous)
static int warningContinueCancel(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const KGuiItem &buttonContinue=KStdGuiItem::cont(), const TQString &dontAskAgainName=TQString::null, int options=Notify)
const char * name(StdAction id)