1 /***************************************************************************
2 docassistant.cpp - Assistant widget
3 -------------------
4 begin : April 2007
5 copyright : (C) 2007 by Klaas Freitag
6 email : freitag@kde.org
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17 #include <QtGui>
18 #include <QDebug>
19 #include <QVBoxLayout>
20 #include <QPushButton>
21 #include <QMessageBox>
22
23 #include <klocalizedstring.h>
24
25 #include "docassistant.h"
26 #include "docpostcard.h"
27 #include "catalogselection.h"
28 #include "textselection.h"
29 #include "kraftsettings.h"
30 #include "kataloglistview.h"
31 #include "doctext.h"
32 #include "defaultprovider.h"
33 #include "headertemplateprovider.h"
34 #include "footertemplateprovider.h"
35 #include "catalogtemplateprovider.h"
36 #include "addresstemplateprovider.h"
37
DocAssistant(QWidget * parent)38 DocAssistant::DocAssistant( QWidget *parent ):
39 QSplitter( parent ), mFullPreview( true ),
40 mActivePage( KraftDoc::Header )
41 {
42 setOrientation( Qt::Vertical );
43
44 QWidget *topWidget = new QWidget;
45 QVBoxLayout *topVBox = new QVBoxLayout;
46 topVBox->setMargin(0);
47 topWidget->setLayout( topVBox );
48
49 QHBoxLayout *buttonLayout = new QHBoxLayout;
50 topVBox->addLayout( buttonLayout );
51
52 QPushButton *pb = new QPushButton( i18n( "Show &Templates" ) );
53 buttonLayout->addWidget( pb );
54 connect( pb, SIGNAL( toggled( bool ) ),
55 this, SLOT( slotToggleShowTemplates( bool ) ) );
56 pb->setCheckable( true );
57 pb->setToolTip( i18n( "Show mask to create or select templates to be used in the document" ) );
58
59 buttonLayout->addStretch();
60 topVBox->addLayout(buttonLayout);
61 mPostCard = new DocPostCard;
62 mPostCard->slotSetMode( DocPostCard::Full, KraftDoc::Header );
63 // setResizeMode( vb /* mPostCard->view() */, KeepSize );
64
65 topVBox->addWidget(mPostCard);
66
67 addWidget(topWidget);
68
69 mTemplatePane = new QWidget;
70 QVBoxLayout *bottomVBox = new QVBoxLayout;
71 bottomVBox->setMargin(0);
72
73 mTemplatePane->setLayout( bottomVBox );
74 addWidget( mTemplatePane );
75
76 setStretchFactor(0, 0);
77 setStretchFactor(1, 0);
78
79 mWidgetStack = new QStackedWidget;
80
81 bottomVBox->addWidget( mWidgetStack );
82 mWidgetStack->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
83
84 /* Selections are the gui reprenentations of the template providing catalogs
85 * like header- and footer texts and catalogs.
86 */
87 mCatalogSelection = new CatalogSelection;
88 mWidgetStack->addWidget( mCatalogSelection );
89 connect( mCatalogSelection, SIGNAL( selectionChanged(QTreeWidgetItem*,QTreeWidgetItem*) ),
90 this, SLOT( slotCatalogSelectionChanged(QTreeWidgetItem*,QTreeWidgetItem*) ) );
91
92 mHeaderSelector = new TextSelection( 0, KraftDoc::Header );
93 mWidgetStack->addWidget( mHeaderSelector );
94
95 connect( mHeaderSelector, SIGNAL(validTemplateSelected() ),
96 this, SLOT( slotTemplateSelectionChanged() ) );
97 connect( mHeaderSelector, SIGNAL(editCurrentTemplate()),
98 this, SLOT(slotEditTemplate()));
99
100 mFooterSelection = new TextSelection( 0, KraftDoc::Footer );
101 mWidgetStack->addWidget( mFooterSelection );
102
103 connect( mFooterSelection, SIGNAL(validTemplateSelected()),
104 this, SLOT(slotTemplateSelectionChanged()));
105 connect( mFooterSelection, SIGNAL(editCurrentTemplate()),
106 this, SLOT(slotEditTemplate()));
107 connect( mFooterSelection, SIGNAL( actionCurrentTextToDoc() ),
108 this, SLOT( slotAddToDocument() ) );
109
110 connect( mPostCard, SIGNAL( selectPage( int ) ),
111 this, SLOT( slotSelectDocPart( int ) ) );
112
113 QHBoxLayout *butHBox2 = new QHBoxLayout;
114 bottomVBox->addLayout( butHBox2 );
115
116 QIcon icons = QIcon::fromTheme( "go-previous" ); // KDE 4 icon name: go-previous
117 mPbAdd = new QPushButton( icons, QString() );
118 mPbAdd->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
119 connect( mPbAdd, SIGNAL( clicked() ), this, SLOT( slotAddToDocument() ) );
120 butHBox2->addWidget( mPbAdd );
121 mPbAdd->setToolTip( i18n( "Add a template to the document" ) );
122
123 icons = QIcon::fromTheme( "document-new" );
124 mPbNew = new QPushButton( icons, QString() ); // KDE 4 icon name: document-new
125 mPbNew->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
126 connect( mPbNew, SIGNAL( clicked() ), this, SLOT( slotNewTemplate() ) );
127 mPbNew->setToolTip( i18n( "Create a new template" ) );
128 butHBox2->addWidget( mPbNew );
129
130 icons = QIcon::fromTheme( "document-properties" );
131 mPbEdit = new QPushButton( icons, QString() ); // KDE 4 icon name: document-properties
132 mPbEdit->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
133 connect( mPbEdit, SIGNAL( clicked() ), this, SLOT( slotEditTemplate() ) );
134 mPbEdit->setToolTip( i18n( "Edit the current template" ) );
135 butHBox2->addWidget( mPbEdit );
136
137 icons = QIcon::fromTheme( "edit-delete" );
138 mPbDel = new QPushButton( icons, QString() ); // KDE 4 icon name: edit-delete
139 mPbDel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
140 connect( mPbDel, SIGNAL( clicked() ), this, SLOT( slotDeleteTemplate() ) );
141 mPbDel->setToolTip( i18n( "Delete the current template" ) );
142 butHBox2->addWidget( mPbDel );
143
144 butHBox2->addStretch();
145
146 mPbAdd->setEnabled( false );
147 mPbNew->setEnabled( false );
148 mPbEdit->setEnabled( false );
149 mPbDel->setEnabled( false );
150
151 /* Template Provider initialisations */
152 mHeaderTemplateProvider = new HeaderTemplateProvider( parent );
153
154 /* get a new header text from the default provider */
155 connect( mHeaderTemplateProvider, SIGNAL( newHeaderText( const DocText& ) ),
156 this, SLOT( slotNewHeaderDocText( const DocText& ) ) );
157 connect( mHeaderTemplateProvider, SIGNAL( updateHeaderText( const DocText& ) ),
158 this, SLOT( slotUpdateHeaderDocText( const DocText& ) ) );
159 connect( mHeaderTemplateProvider, SIGNAL( headerTextToDocument( const DocText& ) ),
160 this, SLOT( slotHeaderTextToDocument( const DocText& ) ) );
161 connect( mHeaderTemplateProvider, SIGNAL( deleteHeaderText( const DocText& ) ),
162 this, SLOT( slotHeaderTextDeleted( const DocText& ) ) );
163 mHeaderTemplateProvider->setSelection( mHeaderSelector );
164
165 mFooterTemplateProvider = new FooterTemplateProvider( parent );
166
167 /* get a new Footer text from the default provider */
168 connect( mFooterTemplateProvider, SIGNAL( newFooterText( const DocText& ) ),
169 this, SLOT( slotNewFooterDocText( const DocText& ) ) );
170 connect( mFooterTemplateProvider, SIGNAL( updateFooterText( const DocText& ) ),
171 this, SLOT( slotUpdateFooterDocText( const DocText& ) ) );
172 connect( mFooterTemplateProvider, SIGNAL( footerTextToDocument( const DocText& ) ),
173 this, SLOT( slotFooterTextToDocument( const DocText& ) ) );
174 connect( mFooterTemplateProvider, SIGNAL( deleteFooterText( const DocText& ) ),
175 this, SLOT( slotFooterTextDeleted( const DocText& ) ) );
176 mFooterTemplateProvider->setSelection( mFooterSelection );
177
178 /* Catalog Template Provider */
179 mCatalogTemplateProvider = new CatalogTemplateProvider( parent );
180 mCatalogTemplateProvider->setCatalogSelection( mCatalogSelection );
181 connect(mCatalogTemplateProvider, &CatalogTemplateProvider::templatesToDocument,
182 this, &DocAssistant::templatesToDocument);
183 mCurrTemplateProvider = mHeaderTemplateProvider;
184
185 const QList<int> sizes = KraftSettings::self()->assistantSplitterSetting();
186 if( sizes.count() > 0 ) {
187 setSizes( sizes );
188 }
189 mTemplatePane->hide();
190 }
191
slotAddToDocument()192 void DocAssistant::slotAddToDocument()
193 {
194 // qDebug () << "SlotAddToDocument called!" << endl;
195 if ( mCurrTemplateProvider ) {
196 mCurrTemplateProvider->slotTemplateToDocument();
197 }
198 }
199
slotTemplateSelectionChanged()200 void DocAssistant::slotTemplateSelectionChanged( )
201 {
202 if (!mCurrTemplateProvider) {
203 mPbNew->setEnabled(false);
204 mPbEdit->setEnabled(false);
205 mPbDel->setEnabled(false);
206 return;
207 }
208
209 if( mActivePage == KraftDoc::Positions ) { // no editing on the catalogs
210 bool enableNew {false};
211
212 auto kat = static_cast<CatalogTemplateProvider*>(mCurrTemplateProvider)->currentCatalog();
213 if (kat->type() == KatalogType::TemplateCatalog) {
214 enableNew = true;
215 }
216 mPbNew->setEnabled(enableNew);
217 mPbEdit->setEnabled( false );
218 mPbDel->setEnabled( false );
219 } else {
220 bool mv {false};
221 if( mActivePage == KraftDoc::Header ) {
222 mv = mHeaderSelector->validSelection();
223 } else if( mActivePage == KraftDoc::Footer ) {
224 mv = mFooterSelection->validSelection();
225 }
226 mPbAdd->setEnabled( mv );
227 mPbNew->setEnabled( true );
228 mPbEdit->setEnabled( mv );
229 mPbDel->setEnabled( mv );
230 }
231 }
232
slotCatalogSelectionChanged(QTreeWidgetItem * current,QTreeWidgetItem *)233 void DocAssistant::slotCatalogSelectionChanged(QTreeWidgetItem *current ,QTreeWidgetItem *)
234 {
235 // enable the move-to-document button.
236 // qDebug () << "catalog position selection changed!" << endl;
237 if ( current ) {
238 mPbAdd->setEnabled( true );
239 } else {
240 mPbAdd->setEnabled( false );
241 }
242 slotTemplateSelectionChanged();
243 }
244
slotNewTemplate()245 void DocAssistant::slotNewTemplate()
246 {
247 /* always set the doc type in case the provider benefits from that */
248 mCurrTemplateProvider->slotSetDocType( mDocType );
249 mCurrTemplateProvider->slotNewTemplate();
250 }
251
252 /* a new header doc text was created and should go to the document */
slotNewHeaderDocText(const DocText & dt)253 void DocAssistant::slotNewHeaderDocText( const DocText& dt )
254 {
255 /* show in list of texts in the GUI */
256 mHeaderSelector->addNewDocText( dt );
257 }
258
259 /* called with a changed text that needs to be updated in the view */
slotUpdateHeaderDocText(const DocText & dt)260 void DocAssistant::slotUpdateHeaderDocText( const DocText& dt )
261 {
262 mHeaderSelector->updateDocText( dt );
263 }
264
265 /* the user hit "add to document" to use a header text template */
slotHeaderTextToDocument(const DocText & dt)266 void DocAssistant::slotHeaderTextToDocument( const DocText& dt )
267 {
268 emit headerTextTemplate( dt.text() );
269 }
270
271 /* a new header doc text was created and should go to the document */
slotNewFooterDocText(const DocText & dt)272 void DocAssistant::slotNewFooterDocText( const DocText& dt )
273 {
274 /* show in list of texts in the GUI */
275 mFooterSelection->addNewDocText( dt );
276 }
277
278 /* called with a changed text that needs to be updated in the view */
slotUpdateFooterDocText(const DocText & dt)279 void DocAssistant::slotUpdateFooterDocText( const DocText& dt )
280 {
281 mFooterSelection->updateDocText( dt );
282 }
283
284 /* the user hit "add to document" to use a header text template */
slotFooterTextToDocument(const DocText & dt)285 void DocAssistant::slotFooterTextToDocument( const DocText& dt )
286 {
287 emit footerTextTemplate( dt.text() );
288 }
289
290 /* Slot that initiates an edit */
slotEditTemplate()291 void DocAssistant::slotEditTemplate()
292 {
293 // qDebug () << "Editing a template using the currentTemplProvider" << endl;
294 if ( mCurrTemplateProvider ) {
295 mCurrTemplateProvider->slotSetDocType( mDocType );
296 mCurrTemplateProvider->slotEditTemplate();
297 }
298 }
299
300 /* slot that initialises a delete, called from the delete button */
slotDeleteTemplate()301 void DocAssistant::slotDeleteTemplate()
302 {
303
304 QMessageBox msgBox;
305 msgBox.setText(i18n( "Do you really want to delete the template permanently?\n"
306 "It can not be recovered."));
307 msgBox.setStandardButtons(QMessageBox::Yes| QMessageBox::No);
308 msgBox.setDefaultButton(QMessageBox::Yes);
309 int ret = msgBox.exec();
310
311 if ( ret == QMessageBox::No ) {
312 return;
313 }
314
315 if ( mCurrTemplateProvider ) {
316 mCurrTemplateProvider->slotDeleteTemplate();
317 }
318 }
319
slotHeaderTextDeleted(const DocText &)320 void DocAssistant::slotHeaderTextDeleted( const DocText& /* dt */)
321 {
322 mHeaderSelector->deleteCurrentText();
323 slotTemplateSelectionChanged( ); // disable the edit buttons etc.
324 }
325
slotFooterTextDeleted(const DocText &)326 void DocAssistant::slotFooterTextDeleted( const DocText& /* dt */)
327 {
328 mFooterSelection->deleteCurrentText();
329 slotTemplateSelectionChanged( ); // disable the edit buttons etc.
330 }
331
332 /* slot that opens the template details in case on == true */
slotToggleShowTemplates(bool on)333 void DocAssistant::slotToggleShowTemplates( bool on )
334 {
335 if ( on ) {
336 // setFullPreview is set in the subslots called from here, that
337 // makes mFullPreview truly reflecting the state of the toggle button
338 if ( mActivePage == KraftDoc::Header ) {
339 slotShowHeaderTemplates();
340 } else if ( mActivePage == KraftDoc::Positions ) {
341 slotShowCatalog();
342 } else if ( mActivePage == KraftDoc::Footer ) {
343 slotShowFooterTemplates();
344 }
345 } else {
346 // hide the details
347 setFullPreview( true, mActivePage );
348 }
349 emit toggleShowTemplates( on );
350 }
351
postCard()352 DocPostCard *DocAssistant::postCard()
353 {
354 return mPostCard;
355 }
356
catalogSelection()357 CatalogSelection* DocAssistant::catalogSelection()
358 {
359 return mCatalogSelection;
360 }
361
362 /* sets the Part of the doc, eg. Header, Footer */
slotSelectDocPart(int p)363 void DocAssistant::slotSelectDocPart( int p )
364 {
365 mActivePage = p;
366 if( mActivePage == KraftDoc::Header ) {
367 mCurrTemplateProvider = mHeaderTemplateProvider;
368 } else if( mActivePage == KraftDoc::Positions ) {
369 mCurrTemplateProvider = mCatalogTemplateProvider;
370 } else if( mActivePage == KraftDoc::Footer ) {
371 mCurrTemplateProvider = mFooterTemplateProvider;
372 } else {
373 // qDebug () << "Alert: Unknown document part id: " << p;
374 }
375 emit selectPage( p );
376 slotToggleShowTemplates( !mFullPreview );
377 slotTemplateSelectionChanged( ); // hide the add, edit- and del buttons
378 }
379
380 /* Doc Type like offer, invoice etc. */
slotSetDocType(const QString & type)381 void DocAssistant::slotSetDocType( const QString& type )
382 {
383 mDocType = type;
384 mHeaderSelector->slotSelectDocType( type );
385 mFooterSelection->slotSelectDocType( type );
386 }
387
slotShowCatalog()388 void DocAssistant::slotShowCatalog( )
389 {
390 setFullPreview( false, KraftDoc::Positions );
391 mWidgetStack->setCurrentWidget( mCatalogSelection );
392 }
393
slotShowHeaderTemplates()394 void DocAssistant::slotShowHeaderTemplates()
395 {
396 setFullPreview( false, KraftDoc::Header );
397 mWidgetStack->setCurrentWidget( mHeaderSelector );
398 }
399
slotShowFooterTemplates()400 void DocAssistant::slotShowFooterTemplates()
401 {
402 setFullPreview( false, KraftDoc::Footer );
403 mWidgetStack->setCurrentWidget( mFooterSelection );
404 }
405
setFullPreview(bool setFull,int id)406 void DocAssistant::setFullPreview( bool setFull, int id )
407 {
408 if ( setFull ) {
409 /* remember the sizes used before */
410 saveSplitterSizes();
411
412 mTemplatePane->hide();
413 mPostCard->slotSetMode( DocPostCard::Full, id );
414 mFullPreview = true;
415 } else {
416 mTemplatePane->show();
417 mPostCard->slotSetMode( DocPostCard::Mini, id );
418
419 if ( KraftSettings::self()->assistantSplitterSetting().size() == 2 ) {
420 QList<int> sizes = KraftSettings::self()->assistantSplitterSetting();
421 if( sizes.contains(0)) {
422 sizes[0] = 50;
423 sizes[1] = 50;
424 }
425 setSizes( sizes );
426 }
427 mFullPreview = false;
428 }
429 }
430
saveSplitterSizes()431 void DocAssistant::saveSplitterSizes()
432 {
433 if( mTemplatePane->isVisible() ) {
434 const QList<int> s = sizes();
435 KraftSettings::self()->setAssistantSplitterSetting( s );
436 }
437 }
438