1 /*
2  *   Copyright 2021 Michael Lang <criticaltemp@protonmail.com>
3  *
4  *   This program is free software; you can redistribute it and/or
5  *   modify it under the terms of the GNU General Public License as
6  *   published by the Free Software Foundation; either version 2 of
7  *   the License, or (at your option) any later version.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *   GNU General Public License for more details.
13  *
14  *   You should have received a copy of the GNU General Public License
15  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "castle.h"
19 
20 // own
21 #include "dealerinfo.h"
22 #include "kpat_debug.h"
23 #include "pileutils.h"
24 #include "settings.h"
25 #include "speeds.h"
26 #include "patsolve/castlesolver.h"
27 // KF
28 #include <KLocalizedString>
29 #include <kwidgetsaddons_version.h>
30 #include <KSelectAction>
31 
32 
Castle(const DealerInfo * di)33 Castle::Castle( const DealerInfo * di )
34   : DealerScene( di )
35 {
36     configOptions();
37     getSavedOptions();
38 }
39 
40 
initialize()41 void Castle::initialize()
42 {
43     setDeckContents( m_decks );
44 
45     const qreal topRowDist = 1.125;
46     const qreal bottomRowDist = 1.125;
47     const qreal offsetY = m_reserves > 0 ? 1.3 : 0;
48 
49     for ( int i = 0; i < m_reserves; ++i )
50     {
51         freecell[i] = new PatPile ( this, 1 + i, QStringLiteral( "freecell%1" ).arg( i ) );
52         freecell[i]->setPileRole(PatPile::Cell);
53         freecell[i]->setLayoutPos(3.25 - topRowDist * (m_reserves - 1) / 2 + topRowDist * i, 0);
54         freecell[i]->setKeyboardSelectHint( KCardPile::AutoFocusTop );
55         freecell[i]->setKeyboardDropHint( KCardPile::AutoFocusTop );
56     }
57 
58     for ( int i = 0; i < m_stacks; ++i )
59     {
60         store[i] = new PatPile( this, 1 + i, QStringLiteral( "store%1" ).arg( i ) );
61         store[i]->setPileRole(PatPile::Tableau);
62         store[i]->setAutoTurnTop(true);
63         if (m_layout == 1) {
64             store[i]->setLayoutPos( 4.5 * (i % 2) + 0, offsetY + bottomRowDist * static_cast<int>((i + 0) / 2 ));
65         } else {
66             store[i]->setLayoutPos( 2.5 * (i % 2) + 2, offsetY + bottomRowDist * static_cast<int>((i + 0) / 2 ));
67         }
68 
69 
70         if (i % 2 || m_layout == 1) {
71             store[i]->setSpread(0.21, 0);
72             store[i]->setRightPadding( 2 );
73             store[i]->setWidthPolicy( KCardPile::GrowRight );
74         } else {
75             store[i]->setSpread(-0.21, 0);
76             store[i]->setLeftPadding( 3 );
77             store[i]->setWidthPolicy( KCardPile::GrowLeft );
78         }
79 
80         store[i]->setKeyboardSelectHint( KCardPile::AutoFocusDeepestRemovable );
81         store[i]->setKeyboardDropHint( KCardPile::AutoFocusTop );
82     }
83 
84     for ( int i = 0; i < 4 * m_decks; ++i )
85     {
86         target[i] = new PatPile( this, 1 + i, QStringLiteral("target%1").arg(i) );
87         target[i]->setPileRole(PatPile::Foundation);
88         target[i]->setLayoutPos(3.25, offsetY + bottomRowDist * i);
89         target[i]->setKeyboardSelectHint( KCardPile::NeverFocus );
90         target[i]->setKeyboardDropHint( KCardPile::ForceFocusTop );
91     }
92 
93     setActions(DealerScene::Demo | DealerScene::Hint);
94     auto solver = new CastleSolver( this );
95     solver->default_max_positions = Settings::castleSolverIterationsLimit();
96     setSolver( solver );
97     setNeededFutureMoves( 4 ); // reserve some
98 }
99 
100 
configActions() const101 QList<QAction*> Castle::configActions() const
102 {
103     return QList<QAction*>() << options << m_emptyStackFillOption << m_sequenceBuiltByOption << m_reservesOption << m_stacksOption << m_stackFaceupOption << m_foundationOption << m_layoutOption;
104 }
105 
106 
gameTypeChanged()107 void Castle::gameTypeChanged()
108 {
109     stopDemo();
110 
111     if ( allowedToStartNewGame() )
112     {
113         if ( m_variation != options->currentItem() )
114         {
115             setOptions(options->currentItem());
116         }
117         else
118         {
119             // update option selections
120             if ( m_emptyStackFill != m_emptyStackFillOption->currentItem() )
121                 m_emptyStackFill = m_emptyStackFillOption->currentItem();
122             else if ( m_sequenceBuiltBy != m_sequenceBuiltByOption->currentItem() )
123                 m_sequenceBuiltBy = m_sequenceBuiltByOption->currentItem();
124             else if ( m_reserves != m_reservesOption->currentItem() )
125                 m_reserves = m_reservesOption->currentItem();
126             else if ( m_stacks - 6 != m_stacksOption->currentItem() )
127                 m_stacks = m_stacksOption->currentItem() + 6;
128             else if ( m_stackFaceup != m_stackFaceupOption->currentItem() )
129                 m_stackFaceup = m_stackFaceupOption->currentItem();
130             else if ( m_foundation != m_foundationOption->currentItem() )
131                 m_foundation = m_foundationOption->currentItem();
132             else if ( m_layout != m_layoutOption->currentItem() )
133                 m_layout = m_layoutOption->currentItem();
134 
135             matchVariant();
136         }
137 
138         // remove existing piles
139         clearPatPiles();
140 
141         initialize();
142         relayoutScene();
143         startNew( gameNumber() );
144         setSavedOptions();
145     }
146     else
147     {
148         // If we're not allowed, reset the options
149         getSavedOptions();
150     }
151 }
152 
153 
restart(const QList<KCard * > & cards)154 void Castle::restart( const QList<KCard*> & cards )
155 {
156     QList<KCard*> cardList = cards;
157 
158     int column = 0;
159     int fdx = 0;
160 
161     // Prefill aces to foundation for select game types
162     if ( m_foundation >= 1 )
163     {
164         for ( int i = 0; i < cardList.size(); ++i )
165         {
166             if (cardList.at(i)->rank() == KCardDeck::Ace)
167             {
168                 addCardForDeal( target[fdx], cardList.takeAt(i), true, target[fdx]->pos() );
169                 --i;
170                 fdx++;
171             }
172         }
173     }
174 
175     bool alternate = false;
176     while ( !cardList.isEmpty() )
177     {
178         // Add matching cards to foundation during deal for select game types
179         if ( m_foundation == 2 && fdx > 0)
180         {
181             KCard * card = cardList.last();
182             int i = 0;
183             for ( i = 0; i < fdx; ++i )
184             {
185                 if ( card->rank() == target[i]->topCard()->rank() + 1 && card->suit() == target[i]->topCard()->suit() )
186                 {
187                     addCardForDeal( target[i], cardList.takeLast(), true, target[i]->pos() );
188                     column = (column + 1) % m_stacks;
189                     break;
190                 }
191             }
192 
193             // Skip if card already added
194             if ( i < fdx ) continue;
195         }
196 
197         bool faceUp = m_stackFaceup == 1 || cardList.length() <= m_stacks || ( m_stackFaceup == 2 && alternate );
198         addCardForDeal( store[column], cardList.takeLast(), faceUp, store[0]->pos() );
199         column = (column + 1) % m_stacks;
200         if ( column % m_stacks == 0)
201             alternate = !alternate;
202     }
203 
204     startDealAnimation();
205 }
206 
207 
solverFormat() const208 QString Castle::solverFormat() const
209 {
210     QString output;
211     QString tmp;
212     for (int i = 0; i < 4 * m_decks ; i++) {
213         if (target[i]->isEmpty())
214             continue;
215         tmp += suitToString(target[i]->topCard()->suit()) + QLatin1Char('-') + rankToString(target[i]->topCard()->rank()) + QLatin1Char(' ');
216     }
217     if (!tmp.isEmpty())
218         output += QStringLiteral("Foundations: %1\n").arg(tmp);
219 
220     tmp.truncate(0);
221     for (int i = 0; i < m_reserves ; i++) {
222         const auto fc = freecell[i];
223         tmp += (fc->isEmpty() ? QStringLiteral("-") : cardToRankSuitString(fc->topCard())) + QLatin1Char(' ');
224     }
225     if (!tmp.isEmpty())
226     {
227         QString a = QStringLiteral("Freecells: %1\n");
228         output += a.arg(tmp);
229     }
230 
231     for (int i = 0; i < m_stacks ; i++)
232         cardsListToLine(output, store[i]->cards());
233     return output;
234 }
235 
236 
cardsDroppedOnPile(const QList<KCard * > & cards,KCardPile * pile)237 void Castle::cardsDroppedOnPile( const QList<KCard*> & cards, KCardPile * pile )
238 {
239     if ( cards.size() <= 1 )
240     {
241         DealerScene::moveCardsToPile( cards, pile, DURATION_MOVE );
242         return;
243     }
244 
245     QList<KCardPile*> freeCells;
246     for ( int i = 0; i < m_reserves; ++i )
247         if ( freecell[i]->isEmpty() )
248             freeCells << freecell[i];
249 
250     QList<KCardPile*> freeStores;
251     for ( int i = 0; i < m_stacks; ++i )
252         if ( store[i]->isEmpty() && store[i] != pile )
253             freeStores << store[i];
254 
255     multiStepMove( cards, pile, freeStores, freeCells, DURATION_MOVE );
256 }
257 
258 
tryAutomaticMove(KCard * c)259 bool Castle::tryAutomaticMove(KCard *c)
260 {
261     // target move
262     if (DealerScene::tryAutomaticMove(c))
263         return true;
264 
265     if (c->isAnimated())
266         return false;
267 
268     if (allowedToRemove(c->pile(), c)
269         && c == c->pile()->topCard())
270     {
271         for (int i = 0; i < m_reserves; i++)
272         {
273             if (allowedToAdd( freecell[i], {c} ))
274             {
275                 moveCardToPile( c, freecell[i], DURATION_MOVE );
276                 return true;
277             }
278         }
279     }
280     return false;
281 }
282 
283 
canPutStore(const KCardPile * pile,const QList<KCard * > & cards) const284 bool Castle::canPutStore( const KCardPile * pile, const QList<KCard*> & cards ) const
285 {
286     int freeCells = 0;
287     for ( int i = 0; i < m_reserves; ++i )
288         if ( freecell[i]->isEmpty() )
289             ++freeCells;
290 
291     int freeStores = 0;
292     if (m_emptyStackFill == 0)
293     {
294         for ( int i = 0; i < m_stacks; ++i )
295             if ( store[i]->isEmpty() && store[i] != pile)
296                 ++freeStores;
297     }
298 
299     if (cards.size() <= (freeCells + 1) << freeStores)
300     {
301         if (pile->isEmpty())
302             return m_emptyStackFill == 0 || (m_emptyStackFill == 1 && cards.first()->rank() == KCardDeck::King);
303         else
304             if (m_sequenceBuiltBy == 1)
305                 return cards.first()->rank() == pile->topCard()->rank() - 1
306                     && cards.first()->suit() == pile->topCard()->suit();
307             else if (m_sequenceBuiltBy == 0)
308                 return cards.first()->rank() == pile->topCard()->rank() - 1
309                     && pile->topCard()->color() != cards.first()->color();
310             else
311                 return cards.first()->rank() == pile->topCard()->rank() - 1;
312     }
313     else
314     {
315         return false;
316     }
317 
318 }
319 
320 
checkAdd(const PatPile * pile,const QList<KCard * > & oldCards,const QList<KCard * > & newCards) const321 bool Castle::checkAdd(const PatPile * pile, const QList<KCard*> & oldCards, const QList<KCard*> & newCards) const
322 {
323     switch (pile->pileRole())
324     {
325     case PatPile::Tableau:
326         return canPutStore(pile, newCards);
327     case PatPile::Cell:
328         return oldCards.isEmpty() && newCards.size() == 1;
329     case PatPile::Foundation:
330         return checkAddSameSuitAscendingFromAce(oldCards, newCards);
331     default:
332         return false;
333     }
334 }
335 
336 
checkRemove(const PatPile * pile,const QList<KCard * > & cards) const337 bool Castle::checkRemove(const PatPile * pile, const QList<KCard*> & cards) const
338 {
339     switch (pile->pileRole())
340     {
341     case PatPile::Tableau:
342         if (m_sequenceBuiltBy == 1)
343             return isSameSuitDescending(cards);
344         else if (m_sequenceBuiltBy == 0)
345             return isAlternateColorDescending(cards);
346         else
347             return isRankDescending(cards);
348     case PatPile::Cell:
349         return cards.first() == pile->topCard();
350     case PatPile::Foundation:
351         return true;
352     default:
353         return false;
354     }
355 }
356 
357 
358 static class CastleDealerInfo : public DealerInfo
359 {
360 public:
CastleDealerInfo()361     CastleDealerInfo()
362       : DealerInfo(I18N_NOOP("Castle"), CastleGeneralId)
363     {
364         addSubtype( CastleBeleagueredId, I18N_NOOP( "Beleaguered Castle" ) );
365         addSubtype( CastleCitadelId, I18N_NOOP( "Citadel" ) );
366         addSubtype( CastleExiledKingsId, I18N_NOOP( "Exiled Kings" ) );
367         addSubtype( CastleStreetAlleyId, I18N_NOOP( "Streets and Alleys" ) );
368         addSubtype( CastleSiegecraftId, I18N_NOOP( "Siegecraft" ) );
369         addSubtype( CastleStrongholdId, I18N_NOOP( "Stronghold" ) );
370         addSubtype( CastleCustomId, I18N_NOOP( "Castle (Custom)" ) );
371     }
372 
createGame() const373     DealerScene *createGame() const override
374     {
375         return new Castle( this );
376     }
377 } castleDealerInfo;
378 
379 
matchVariant()380 void Castle::matchVariant()
381 {
382     if ( m_emptyStackFill == 0 && m_sequenceBuiltBy == 2 && m_reserves == 0  && m_stacks == 8 && m_foundation == 1 )
383         m_variation = 0;
384     else if ( m_emptyStackFill == 0 && m_sequenceBuiltBy == 2 && m_reserves == 0  && m_stacks == 8 && m_foundation == 2 )
385         m_variation = 1;
386     else if ( m_emptyStackFill == 1 && m_sequenceBuiltBy == 2 && m_reserves == 0  && m_stacks == 8 && m_foundation == 2 )
387         m_variation = 2;
388     else if ( m_emptyStackFill == 0 && m_sequenceBuiltBy == 2 && m_reserves == 0  && m_stacks == 8 && m_foundation == 0 )
389         m_variation = 3;
390     else if ( m_emptyStackFill == 0 && m_sequenceBuiltBy == 2 && m_reserves == 1  && m_stacks == 8 && m_foundation == 1 )
391         m_variation = 4;
392     else if ( m_emptyStackFill == 0 && m_sequenceBuiltBy == 2 && m_reserves == 1  && m_stacks == 8 && m_foundation == 0 )
393         m_variation = 5;
394     else
395         m_variation = 6;
396 
397     options->setCurrentItem( m_variation );
398 }
399 
400 
configOptions()401 void Castle::configOptions()
402 {
403     options = new KSelectAction(i18n("Popular Variant Presets"), this );
404     options->addAction( i18n("Beleaguered Castle") );
405     options->addAction( i18n("Citadel") );
406     options->addAction( i18n("Exiled Kings") );
407     options->addAction( i18n("Streets and Alleys") );
408     options->addAction( i18n("Siegecraft") );
409     options->addAction( i18n("Stronghold") );
410     options->addAction( i18n("Custom") );
411 
412     m_emptyStackFillOption = new KSelectAction(i18n("Empty Stack Fill"), this );
413     m_emptyStackFillOption->addAction( i18n("Any (Easy)") );
414     m_emptyStackFillOption->addAction( i18n("Kings only (Medium)") );
415     m_emptyStackFillOption->addAction( i18n("None (Hard)") );
416 
417     m_sequenceBuiltByOption = new KSelectAction(i18n("Build Sequence"), this );
418     m_sequenceBuiltByOption->addAction( i18n("Alternating Color") );
419     m_sequenceBuiltByOption->addAction( i18n("Matching Suit") );
420     m_sequenceBuiltByOption->addAction( i18n("Rank") );
421 
422     m_reservesOption = new KSelectAction(i18n("Free Cells"), this );
423     m_reservesOption->addAction( i18n("0") );
424     m_reservesOption->addAction( i18n("1") );
425     m_reservesOption->addAction( i18n("2") );
426     m_reservesOption->addAction( i18n("3") );
427     m_reservesOption->addAction( i18n("4") );
428 
429     m_stacksOption = new KSelectAction(i18n("Stacks"), this );
430     m_stacksOption->addAction( i18n("6") );
431     m_stacksOption->addAction( i18n("7") );
432     m_stacksOption->addAction( i18n("8") );
433     m_stacksOption->addAction( i18n("9") );
434     m_stacksOption->addAction( i18n("10") );
435 
436     m_stackFaceupOption = new KSelectAction(i18n("S&tack Options"), this );
437     m_stackFaceupOption->addAction( i18n("Face &Down") );
438     m_stackFaceupOption->addAction( i18n("Face &Up") );
439     m_stackFaceupOption->addAction( i18n("Alternating Face &Up") );
440 
441     m_foundationOption = new KSelectAction(i18n("Foundation Deal"), this );
442     m_foundationOption->addAction( i18n("None") );
443     m_foundationOption->addAction( i18n("Aces") );
444     m_foundationOption->addAction( i18n("Any") );
445 
446     m_layoutOption = new KSelectAction(i18n("Layout"), this );
447     m_layoutOption->addAction( i18n("Classic") );
448     m_layoutOption->addAction( i18n("Modern") );
449 
450 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 78, 0)
451     connect(options, &KSelectAction::indexTriggered, this, &Castle::gameTypeChanged);
452     connect(m_emptyStackFillOption, &KSelectAction::indexTriggered, this, &Castle::gameTypeChanged);
453     connect(m_reservesOption, &KSelectAction::indexTriggered, this, &Castle::gameTypeChanged);
454     connect(m_sequenceBuiltByOption, &KSelectAction::indexTriggered, this, &Castle::gameTypeChanged);
455     connect(m_stacksOption, &KSelectAction::indexTriggered, this, &Castle::gameTypeChanged);
456     connect(m_stackFaceupOption, &KSelectAction::indexTriggered, this, &Castle::gameTypeChanged);
457     connect(m_foundationOption, &KSelectAction::indexTriggered, this, &Castle::gameTypeChanged);
458     connect(m_layoutOption, &KSelectAction::indexTriggered, this, &Castle::gameTypeChanged);
459 #else
460     connect(options, static_cast<void (KSelectAction::*)(int)>(&KSelectAction::triggered), this, &Castle::gameTypeChanged);
461     connect(m_emptyStackFillOption, static_cast<void (KSelectAction::*)(int)>(&KSelectAction::triggered), this, &Castle::gameTypeChanged);
462     connect(m_reservesOption, static_cast<void (KSelectAction::*)(int)>(&KSelectAction::triggered), this, &Castle::gameTypeChanged);
463     connect(m_sequenceBuiltByOption, static_cast<void (KSelectAction::*)(int)>(&KSelectAction::triggered), this, &Castle::gameTypeChanged);
464     connect(m_stacksOption, static_cast<void (KSelectAction::*)(int)>(&KSelectAction::triggered), this, &Castle::gameTypeChanged);
465     connect(m_stackFaceupOption, static_cast<void (KSelectAction::*)(int)>(&KSelectAction::triggered), this, &Castle::gameTypeChanged);
466     connect(m_foundationOption, static_cast<void (KSelectAction::*)(int)>(&KSelectAction::triggered), this, &Castle::gameTypeChanged);
467     connect(m_layoutOption, static_cast<void (KSelectAction::*)(int)>(&KSelectAction::triggered), this, &Castle::gameTypeChanged);
468 #endif
469 }
470 
471 
setSavedOptions()472 void Castle::setSavedOptions()
473 {
474     Settings::setCastleEmptyStackFill( m_emptyStackFill );
475     Settings::setCastleSequenceBuiltBy( m_sequenceBuiltBy );
476     Settings::setCastleReserves( m_reserves );
477     Settings::setCastleStacks( m_stacks );
478     Settings::setCastleStackFaceup( m_stackFaceup );
479     Settings::setCastleFoundation( m_foundation );
480     Settings::setCastleLayout( m_layout );
481 }
482 
483 
getSavedOptions()484 void Castle::getSavedOptions()
485 {
486     m_emptyStackFill = Settings::castleEmptyStackFill();
487     m_sequenceBuiltBy = Settings::castleSequenceBuiltBy();
488     m_reserves = Settings::castleReserves();
489     m_stacks = Settings::castleStacks();
490     m_stackFaceup = Settings::castleStackFaceup();
491     m_foundation = Settings::castleFoundation();
492     m_layout = Settings::castleLayout();
493     m_decks = 1;
494 
495     if ( m_stacks < 6) m_stacks = 6;
496 
497     matchVariant();
498 
499     m_emptyStackFillOption->setCurrentItem( m_emptyStackFill );
500     m_sequenceBuiltByOption->setCurrentItem( m_sequenceBuiltBy );
501     m_reservesOption->setCurrentItem( m_reserves );
502     m_stacksOption->setCurrentItem( m_stacks - 6 );
503     m_stackFaceupOption->setCurrentItem( m_stackFaceup );
504     m_foundationOption->setCurrentItem( m_foundation );
505     m_layoutOption->setCurrentItem( m_layout );
506 }
507 
508 
mapOldId(int id)509 void Castle::mapOldId(int id)
510 {
511     switch (id) {
512 
513     case DealerInfo::CastleBeleagueredId :
514         setOptions(0);
515         break;
516     case DealerInfo::CastleCitadelId :
517         setOptions(1);
518         break;
519     case DealerInfo::CastleExiledKingsId :
520         setOptions(2);
521         break;
522     case DealerInfo::CastleStreetAlleyId :
523         setOptions(3);
524         break;
525     case DealerInfo::CastleSiegecraftId :
526         setOptions(4);
527         break;
528     case DealerInfo::CastleStrongholdId :
529         setOptions(5);
530         break;
531     case DealerInfo::CastleCustomId :
532         setOptions(6);
533         break;
534     default:
535         // Do nothing.
536         break;
537     }
538 }
539 
540 
oldId() const541 int Castle::oldId() const
542 {
543     switch (m_variation) {
544     case 0 :
545         return DealerInfo::CastleBeleagueredId;
546     case 1 :
547         return DealerInfo::CastleCitadelId;
548     case 2 :
549         return DealerInfo::CastleExiledKingsId;
550     case 3 :
551         return DealerInfo::CastleStreetAlleyId;
552     case 4 :
553         return DealerInfo::CastleSiegecraftId;
554     case 5 :
555         return DealerInfo::CastleStrongholdId;
556     default :
557         return DealerInfo::CastleCustomId;
558     }
559 }
560 
561 
setOptions(int variation)562 void Castle::setOptions(int variation)
563 {
564     if ( variation != m_variation )
565     {
566         m_variation = variation;
567         m_emptyStackFill = 0;
568         m_sequenceBuiltBy = 2;
569         m_reserves = 0;
570         m_stacks = 8;
571         m_stackFaceup = 1;
572         m_decks = 1;
573         m_foundation = 1;
574 
575         switch (m_variation) {
576         case 0 :
577             break;
578         case 1 :
579             m_foundation = 2;
580             break;
581         case 2 :
582             m_foundation = 2;
583             m_emptyStackFill = 1;
584             break;
585         case 3 :
586             m_foundation = 0;
587             break;
588         case 4 :
589             m_reserves = 1;
590             break;
591         case 5 :
592             m_foundation = 0;
593             m_reserves = 1;
594             break;
595         case 6 :
596             m_sequenceBuiltBy = 0;
597             break;
598         }
599 
600         m_emptyStackFillOption->setCurrentItem( m_emptyStackFill );
601         m_sequenceBuiltByOption->setCurrentItem( m_sequenceBuiltBy );
602         m_reservesOption->setCurrentItem( m_reserves );
603         m_stacksOption->setCurrentItem( m_stacks - 6 );
604         m_stackFaceupOption->setCurrentItem( m_stackFaceup );
605         m_foundationOption->setCurrentItem( m_foundation );
606     }
607 }
608 
609