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