summaryrefslogtreecommitdiff
path: root/quacker
diff options
context:
space:
mode:
Diffstat (limited to 'quacker')
-rw-r--r--quacker/Info.plist2
-rw-r--r--quacker/boardsetupdialog.cpp23
-rw-r--r--quacker/boardsetupdialog.h2
-rw-r--r--quacker/graphicalreporter.cpp1
-rw-r--r--quacker/lexicondialog.cpp306
-rw-r--r--quacker/lexicondialog.h86
-rw-r--r--quacker/lister.cpp3
-rw-r--r--quacker/quacker.cpp36
-rw-r--r--quacker/quacker.plist2
-rw-r--r--quacker/quacker.pro17
-rw-r--r--quacker/settings.cpp380
-rw-r--r--quacker/settings.h32
12 files changed, 739 insertions, 151 deletions
diff --git a/quacker/Info.plist b/quacker/Info.plist
index 015f161..854c8a9 100644
--- a/quacker/Info.plist
+++ b/quacker/Info.plist
@@ -26,7 +26,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>0.98</string>
+ <string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
diff --git a/quacker/boardsetupdialog.cpp b/quacker/boardsetupdialog.cpp
index 7198b17..2bfd5ff 100644
--- a/quacker/boardsetupdialog.cpp
+++ b/quacker/boardsetupdialog.cpp
@@ -33,7 +33,7 @@
BoardSetupDialog::BoardSetupDialog(QWidget *parent) : QDialog(parent)
{
- resize(600,450);
+ resize(700,550);
setSizeGripEnabled(true);
// construct the board
@@ -58,6 +58,7 @@ BoardSetupDialog::BoardSetupDialog(QWidget *parent) : QDialog(parent)
m_saveChanges = new QPushButton(tr("&Save Changes"));
m_cancel = new QPushButton(tr("&Cancel"));
m_undoAll = new QPushButton(tr("&Undo All Changes"));
+ m_deleteBoard = new QPushButton(tr("&Delete Board"));
QVBoxLayout * superLayout = new QVBoxLayout;
Geometry::setupFramedLayout(superLayout);
@@ -96,6 +97,8 @@ BoardSetupDialog::BoardSetupDialog(QWidget *parent) : QDialog(parent)
leftSideLayout->addWidget(dimensionGroup);
leftSideLayout->addWidget(symmetryGroup);
leftSideLayout->addWidget(m_undoAll);
+ if (!m_originalName.isEmpty())
+ leftSideLayout->addWidget(m_deleteBoard);
leftSideLayout->addStretch();
mainLayout->addLayout(leftSideLayout);
@@ -118,6 +121,7 @@ BoardSetupDialog::BoardSetupDialog(QWidget *parent) : QDialog(parent)
connect(m_saveChanges, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_cancel, SIGNAL(clicked()), this, SLOT(reject()));
connect(m_undoAll, SIGNAL(clicked()), this, SLOT(undoAllChanges()));
+ connect(m_deleteBoard, SIGNAL(clicked()), this, SLOT(deleteBoard()));
connect(m_horizontalSymmetry, SIGNAL(stateChanged(int)), this, SLOT(symmetryChanged()));
connect(m_verticalSymmetry, SIGNAL(stateChanged(int)), this, SLOT(symmetryChanged()));
connect(m_diagonalSymmetry, SIGNAL(stateChanged(int)), this, SLOT(symmetryChanged()));
@@ -239,3 +243,20 @@ void BoardSetupDialog::undoAllChanges()
QUACKLE_DATAMANAGER->setBoardParameters(Quackle::BoardParameters::Deserialize(boardStream));
parametersChanged(QString());
}
+
+void BoardSetupDialog::deleteBoard()
+{
+ QString message = "Do you really want to delete the game board \"";
+ message += m_originalName;
+ message += "\"?";
+ if (QMessageBox::warning(NULL, QString("Confirm Deletion"), message,
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::No | QMessageBox::Escape) == QMessageBox::Yes)
+ {
+ CustomQSettings settings;
+ settings.beginGroup("quackle/boardparameters");
+ settings.remove(m_originalName);
+ QDialog::reject();
+ }
+}
+
diff --git a/quacker/boardsetupdialog.h b/quacker/boardsetupdialog.h
index e5432cc..0176d1a 100644
--- a/quacker/boardsetupdialog.h
+++ b/quacker/boardsetupdialog.h
@@ -48,6 +48,7 @@ protected slots:
void parametersChanged(const QString &unused);
void symmetryChanged();
void undoAllChanges();
+ void deleteBoard();
private:
QCheckBox *m_horizontalSymmetry;
@@ -62,6 +63,7 @@ private:
QPushButton *m_saveChanges;
QPushButton *m_cancel;
QPushButton *m_undoAll;
+ QPushButton *m_deleteBoard;
Quackle::Game m_game;
BoardSetupFrame * m_boardFrame;
diff --git a/quacker/graphicalreporter.cpp b/quacker/graphicalreporter.cpp
index f7c9ce7..2fb0842 100644
--- a/quacker/graphicalreporter.cpp
+++ b/quacker/graphicalreporter.cpp
@@ -227,5 +227,6 @@ void GraphicalReporter::openIndex()
m_indexStream.setDevice(&m_indexFile);
}
+ m_indexStream.setCodec(QTextCodec::codecForName("UTF-8"));
}
diff --git a/quacker/lexicondialog.cpp b/quacker/lexicondialog.cpp
new file mode 100644
index 0000000..91eb676
--- /dev/null
+++ b/quacker/lexicondialog.cpp
@@ -0,0 +1,306 @@
+/*
+ * Quackle -- Crossword game artificial intelligence and analysis tool
+ * Copyright (C) 2005-2014 Jason Katz-Brown and John O'Laughlin.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sstream>
+#include <QtGui>
+#include <datamanager.h>
+#include <quackleio/util.h>
+
+#include "lexicondialog.h"
+#include "customqsettings.h"
+#include "settings.h"
+#include "geometry.h"
+#include "quackleio/dawgfactory.h"
+
+class FileNameValidator : public QValidator
+{
+public:
+ virtual State validate(QString &input, int &pos) const
+ {
+ for (QString::ConstIterator i = input.begin(); i != input.end(); ++i)
+ if (*i == '/' || *i == '?' || *i == '\\' || *i == '*')
+ return Invalid;
+ return Acceptable;
+ }
+};
+
+LexiconDialog::LexiconDialog(QWidget *parent, const QString &originalName) : QDialog(parent),
+ m_deleted(false), m_wordFactory(NULL)
+{
+ m_originalName = originalName;
+
+ resize(450,350);
+
+ // construct the UI elements
+ m_lexiconName = new QLineEdit();
+ m_alphabetCombo = new QComboBox();
+ m_fileNameValidator = new FileNameValidator();
+
+ m_addWordsFromFile = new QPushButton(tr("Add words from &file..."));
+ m_clearAllWords = new QPushButton(tr("Clear &words and start again"));
+
+
+ m_lexiconInformation = new QLabel("");
+ m_lexiconInformation->setWordWrap(true);
+ m_lexiconInformation->setTextInteractionFlags(Qt::TextBrowserInteraction);
+
+ m_saveChanges = new QPushButton(tr("&Save Changes"));
+ m_cancel = new QPushButton(tr("&Cancel"));
+ m_deleteLexicon = new QPushButton(tr("&Delete Lexicon"));
+
+ QLabel * lexiconNameLabel = new QLabel(tr("&Lexicon name:"));
+ QLabel * alphabetLabel = new QLabel(tr("&Alphabet:"));
+ lexiconNameLabel->setBuddy(m_lexiconName);
+ alphabetLabel->setBuddy(m_alphabetCombo);
+
+ QVBoxLayout * layout = new QVBoxLayout;
+ Geometry::setupFramedLayout(layout);
+ QHBoxLayout * lexiconRow = new QHBoxLayout;
+ Geometry::setupInnerLayout(lexiconRow);
+ QHBoxLayout * addRemoveWordsRow = new QHBoxLayout;
+ Geometry::setupInnerLayout(addRemoveWordsRow);
+ QHBoxLayout * buttonRow = new QHBoxLayout;
+ Geometry::setupInnerLayout(buttonRow);
+ QGroupBox * lexiconInformationGroup = new QGroupBox(tr("Lexicon information"));
+ QVBoxLayout * lexiconInformationLayout = new QVBoxLayout(lexiconInformationGroup);
+
+ // build the layout
+ lexiconRow->addWidget(lexiconNameLabel);
+ lexiconRow->addWidget(m_lexiconName);
+ lexiconRow->addStretch();
+ lexiconRow->addWidget(alphabetLabel);
+ lexiconRow->addWidget(m_alphabetCombo);
+
+ addRemoveWordsRow->addWidget(m_addWordsFromFile);
+ addRemoveWordsRow->addWidget(m_clearAllWords);
+
+ lexiconInformationLayout->addWidget(m_lexiconInformation);
+
+ buttonRow->addWidget(m_deleteLexicon);
+ buttonRow->addStretch();
+ buttonRow->addWidget(m_cancel);
+ buttonRow->addWidget(m_saveChanges);
+
+ layout->addLayout(lexiconRow);
+ layout->addLayout(addRemoveWordsRow);
+ layout->addWidget(lexiconInformationGroup);
+ layout->addStretch();
+ layout->addLayout(buttonRow);
+
+ setLayout(layout);
+ m_saveChanges->setDefault(true);
+
+ // hook up signals and slots
+ connect(m_lexiconName, SIGNAL(textEdited(const QString &)), this, SLOT(parametersChanged(const QString &)));
+ connect(m_addWordsFromFile, SIGNAL(clicked()), this, SLOT(addWordsFromFile()));
+ connect(m_clearAllWords, SIGNAL(clicked()), this, SLOT(loadOriginalDictionary()));
+ connect(m_saveChanges, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(m_cancel, SIGNAL(clicked()), this, SLOT(reject()));
+ connect(m_deleteLexicon, SIGNAL(clicked()), this, SLOT(deleteLexicon()));
+ connect(m_alphabetCombo, SIGNAL(activated(const QString &)), this, SLOT(alphabetChanged(const QString &)));
+
+ setWindowTitle(tr("Configure Lexicon - Quackle"));
+
+ Settings::populateComboFromFilenames(m_alphabetCombo, "alphabets", ".quackle_alphabet", "");
+ m_alphabetCombo->setCurrentIndex(m_alphabetCombo->findText(QuackleIO::Util::stdStringToQString(QUACKLE_ALPHABET_PARAMETERS->alphabetName())));
+ alphabetChanged(m_alphabetCombo->currentText());
+
+ m_lexiconName->setValidator(m_fileNameValidator);
+ m_lexiconName->setText(m_originalName);
+
+ loadOriginalDictionary();
+}
+
+LexiconDialog::~LexiconDialog()
+{
+ delete m_fileNameValidator;
+ delete m_wordFactory;
+}
+
+void LexiconDialog::deleteLexicon()
+{
+ string lexiconNameStr = m_originalName.toStdString();
+ string filename = QUACKLE_DATAMANAGER->makeDataFilename("lexica", lexiconNameStr + ".dawg", true);
+ QFile(QString::fromStdString(filename)).remove();
+ m_deleted = true;
+ QDialog::accept();
+}
+
+void LexiconDialog::addWordsFromFile()
+{
+ QFileDialog browser(this, tr("Choose a file containing words to be added to the lexicon..."));
+ QStringList filters;
+ filters << "Dictionary files (*.txt *.dawg *.raw)"
+ << "All files (*.*)";
+ browser.setNameFilters(filters);
+ browser.setFileMode(QFileDialog::ExistingFiles);
+ browser.exec();
+
+ QStringList files = browser.selectedFiles();
+ for (QList<QString>::const_iterator it = files.begin(); it != files.end(); it++)
+ {
+ if (it->endsWith(".dawg", Qt::CaseInsensitive))
+ addWordsFromDawgFile(*it);
+ else
+ addWordsFromTextFile(*it);
+ }
+ updateLexiconInformation();
+}
+
+void LexiconDialog::alphabetChanged(const QString &alphabet)
+{
+ delete m_wordFactory;
+ m_wordFactory = NULL;
+ updateLexiconInformation();
+ m_alphabetFileName = QString::fromStdString(AlphabetParameters::findAlphabetFile(QuackleIO::Util::qstringToStdString(alphabet)));
+}
+
+void LexiconDialog::addWordsFromDawgFile(const QString &dawgfile)
+{
+ if (!m_wordFactory)
+ m_wordFactory = new DawgFactory(m_alphabetFileName);
+ LexiconParameters lexParams;
+ lexParams.loadDawg(QuackleIO::Util::qstringToStdString(dawgfile));
+ if (!lexParams.hasDawg())
+ return;
+
+ Quackle::LetterString word;
+
+ addWordsFromDawgRecursive(lexParams, word, 1);
+}
+
+void LexiconDialog::addWordsFromDawgRecursive(const LexiconParameters &lexParams, Quackle::LetterString &word, int index)
+{
+ unsigned int p;
+ Quackle::Letter letter;
+ bool t;
+ bool lastchild;
+ bool british;
+ int playability;
+
+ do
+ {
+ lexParams.dawgAt(index, p, letter, t, lastchild, british, playability);
+ word.push_back(letter);
+ if (t)
+ m_wordFactory->pushWord(word, !british, playability);
+ if (p)
+ addWordsFromDawgRecursive(lexParams, word, p);
+ index++;
+ word.pop_back();
+ } while (!lastchild);
+}
+
+void LexiconDialog::addWordsFromTextFile(const QString &textFile)
+{
+ if (!m_wordFactory)
+ m_wordFactory = new DawgFactory(m_alphabetFileName);
+
+ QFile file(textFile);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return;
+
+ QTextStream stream(&file);
+ stream.setCodec("UTF-8");
+ QString word;
+ while (!stream.atEnd())
+ {
+ stream >> word;
+ word = word.trimmed().toUpper();
+ if (word.isEmpty())
+ continue;
+ QChar firstChar = word[0];
+ if (firstChar < 'A')
+ continue; // allows the usage of most punctuation characters as comments
+ int playability = 0;
+ for (int i = word.size() - 1; i > 0; i--)
+ {
+ if (word[i].isDigit())
+ playability = playability * 10 + word[i].digitValue();
+ }
+ m_wordFactory->pushWord(QuackleIO::Util::qstringToString(word), true, playability);
+ }
+}
+
+void LexiconDialog::loadOriginalDictionary()
+{
+ delete m_wordFactory;
+ m_wordFactory = NULL;
+ string dawgFileName = m_originalName.toStdString() + ".dawg";
+ QString dawgFullFileName;
+ if (!m_originalName.isEmpty())
+ dawgFullFileName = QString::fromStdString(Quackle::LexiconParameters::findDictionaryFile(dawgFileName));
+
+ if (!dawgFullFileName.isEmpty())
+ {
+ m_deleteLexicon->setEnabled(Quackle::LexiconParameters::hasUserDictionaryFile(dawgFileName));
+ m_lexiconInformation->setText(tr("Loading dictionary..."));
+ show();
+ qApp->processEvents();
+ addWordsFromDawgFile(dawgFullFileName);
+ }
+ else
+ m_deleteLexicon->setEnabled(false);
+
+ updateLexiconInformation(true);
+}
+
+void LexiconDialog::accept()
+{
+ string lexiconNameStr = m_lexiconName->text().toStdString();
+ string filename = QUACKLE_DATAMANAGER->makeDataFilename("lexica", lexiconNameStr + ".dawg", true);
+ m_lexiconInformation->setText(tr("Compressing and writing dictionary file...\nThis may take a few minutes."));
+ qApp->processEvents();
+ m_wordFactory->generate();
+ m_lexiconInformation->setText(tr("Writing dictionary file..."));
+ qApp->processEvents();
+ m_wordFactory->writeIndex(filename);
+ m_finalLexiconName = m_lexiconName->text();
+ QDialog::accept();
+}
+
+void LexiconDialog::updateLexiconInformation(bool firstTime)
+{
+ QByteArray hash = m_wordFactory ? QByteArray(m_wordFactory->hashBytes(), 16).toHex() : "";
+ QString text;
+ QString lengthText;
+
+ int wordCount = m_wordFactory ? m_wordFactory->wordCount() : 0;
+ if (wordCount == 0)
+ {
+ delete m_wordFactory;
+ m_wordFactory = NULL;
+ }
+ if (m_wordFactory)
+ lengthText = QString::fromStdString(m_wordFactory->letterCountString());
+
+ if (firstTime)
+ m_originalHash = hash;
+
+ text.append(tr("Word count: "));
+ text.append(QString("%L1").arg(wordCount));
+ text.append("\n");
+ text.append(lengthText);
+ text.append(tr("\nLexicon hash: "));
+ text.append(hash.left(8));
+
+ m_lexiconInformation->setText(text);
+
+ m_saveChanges->setEnabled(true/*hash != m_originalHash && !m_lexiconName->text().isEmpty()*/);
+ m_clearAllWords->setEnabled(hash != m_originalHash);
+}
diff --git a/quacker/lexicondialog.h b/quacker/lexicondialog.h
new file mode 100644
index 0000000..1f1605b
--- /dev/null
+++ b/quacker/lexicondialog.h
@@ -0,0 +1,86 @@
+/*
+ * Quackle -- Crossword game artificial intelligence and analysis tool
+ * Copyright (C) 2005-2014 Jason Katz-Brown and John O'Laughlin.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QUACKER_LEXICONDIALOG_H
+#define QUACKER_LEXICONDIALOG_H
+
+#include <string>
+#include "game.h"
+#include "lexiconparameters.h"
+
+#include <QWidget>
+#include <QDialog>
+
+using namespace std;
+using namespace Quackle;
+
+class QComboBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class DawgFactory;
+class FileNameValidator;
+
+class LexiconDialog : public QDialog
+{
+Q_OBJECT
+
+public:
+ LexiconDialog(QWidget *parent = 0, const QString &originalName = QString());
+ ~LexiconDialog();
+ virtual void accept();
+
+ bool itemWasDeleted() { return m_deleted; };
+ const QString &lexiconName() { return m_finalLexiconName; };
+
+ void updateLexiconInformation(bool firstTime = false);
+
+protected slots:
+ void parametersChanged(const QString &) { updateLexiconInformation(); };
+ void deleteLexicon();
+ void addWordsFromFile();
+ void alphabetChanged(const QString &);
+ void loadOriginalDictionary();
+
+protected:
+ void addWordsFromDawgFile(const QString &dawgfile);
+ void addWordsFromDawgRecursive(const LexiconParameters &lexParams, Quackle::LetterString &word, int index);
+ void addWordsFromTextFile(const QString &textFile);
+
+private:
+ QLineEdit *m_lexiconName;
+ QComboBox *m_alphabetCombo;
+ QPushButton *m_addWordsFromFile;
+ QPushButton *m_clearAllWords;
+ QLabel *m_lexiconInformation;
+ FileNameValidator * m_fileNameValidator;
+
+ QPushButton *m_saveChanges;
+ QPushButton *m_cancel;
+ QPushButton *m_deleteLexicon;
+
+ QString m_originalName;
+ QString m_alphabetFileName;
+ QByteArray m_originalHash;
+ QString m_finalLexiconName;
+ bool m_deleted;
+
+ DawgFactory *m_wordFactory;
+};
+
+#endif
diff --git a/quacker/lister.cpp b/quacker/lister.cpp
index 278bff1..be3e335 100644
--- a/quacker/lister.cpp
+++ b/quacker/lister.cpp
@@ -667,7 +667,6 @@ void NumAnagramsFilter::apply()
{
int twl = 0;
int british = 0;
- int playability = 0;
QString alphagram(QuackleIO::DictFactory::querier()->alphagram((*it).word));
for (Dict::WordList::Iterator word = map[alphagram].begin(); word != map[alphagram].end(); ++word)
@@ -676,8 +675,6 @@ void NumAnagramsFilter::apply()
british++;
else
twl++;
-
- playability += (*word).playability;
}
if ((twl == numTwlAnagrams) && (british == numOswOnlyAnagrams))
diff --git a/quacker/quacker.cpp b/quacker/quacker.cpp
index 098ff84..2f407fa 100644
--- a/quacker/quacker.cpp
+++ b/quacker/quacker.cpp
@@ -155,13 +155,10 @@ void TopLevel::finishInitialization()
void TopLevel::introduceToUser()
{
CustomQSettings settings;
- QString lexiconName = settings.value("quackle/settings/lexicon-name", QString("twl06")).toString();
- if (lexiconName == "csw12") {
- statusMessage(tr("The WESPA wordlist (CSW12) is copyright Harper Collins 2011."));
- } else {
- statusMessage(tr("Enjoy your quackling. Choose \"New game...\" from the Game menu to begin."));
- }
-
+ QString statusText = QString::fromUtf8(QUACKLE_LEXICON_PARAMETERS->copyrightString().c_str());
+ if (statusText.isEmpty())
+ statusText = tr("Enjoy your quackling. Choose \"New game...\" from the Game menu to begin.");
+ statusMessage(statusText);
parseCommandLineOptions();
if (!CustomQSettings().contains("quackle/hasBeenRun"))
@@ -2120,17 +2117,34 @@ void TopLevel::firstTimeRun()
void TopLevel::about()
{
- QMessageBox::about(this, tr("About Quackle 0.98"), dialogText(tr(
-"<p><b>Quackle</b> 0.98 is a crossword game playing, analysis, and study tool. Visit the Quackle homepage at <tt><a href=\"http://quackle.org\">http://quackle.org</a></tt> for more information.</p>"
+ QString aboutText = tr(
+"<p><b>Quackle</b> 1.0 is a crossword game playing, analysis, and study tool. Visit the Quackle homepage at <tt><a href=\"http://quackle.org\">http://quackle.org</a></tt> for more information.</p>"
"<p>Quackle was written by Jason Katz-Brown, John O'Laughlin, John Fultz, Matt Liberty, and Anand Buddhdev. We thank the anonymous donor who made this software free.</p>"
-"<p>Copyright 2005-2014 by</p>"
+"<p>Copyright 2005-2015 by</p>"
"<ul>"
"<li>Jason Katz-Brown &lt;jasonkatzbrown@gmail.com&gt;</li>"
"<li>John O'Laughlin &lt;olaughlin@gmail.com&gt;</li>"
"</ul>"
"<p>Quackle is free, open-source software licensed under the terms of the GNU General Public License Version 3. See</p>"
"<p><tt><a href=\"http://quackle.org/LICENSE\">http://quackle.org/LICENSE</a></tt></p>"
-)));
+"<p>Dictionary copyrights</p><ul>"
+);
+
+ FILE* file = fopen(QUACKLE_DATAMANAGER->makeDataFilename("lexica", "copyrights.txt", false).c_str(), "r");
+ if (file)
+ {
+ QTextStream strm(file);
+ while (!strm.atEnd())
+ {
+ QString line = strm.readLine();
+ int pos = line.indexOf(':');
+ if (pos != -1 && pos + 1 < line.size())
+ aboutText += "<li>" + line.mid(pos + 1) + "</li>";
+ }
+ fclose(file);
+ aboutText += "</ul>";
+ }
+ QMessageBox::about(this, tr("About Quackle 1.0"), dialogText(aboutText));
}
void TopLevel::hints()
diff --git a/quacker/quacker.plist b/quacker/quacker.plist
index bf6b31e..eef0ac9 100644
--- a/quacker/quacker.plist
+++ b/quacker/quacker.plist
@@ -21,6 +21,6 @@
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHumanReadableCopyright</key>
- <string>Copyright &copy; 2005-2013 by Jason Katz-Brown & John O'Laughlin</string>
+ <string>Copyright &copy; 2005-2015 by Jason Katz-Brown & John O'Laughlin</string>
</dict>
</plist>
diff --git a/quacker/quacker.pro b/quacker/quacker.pro
index 9906e45..6e3f2e0 100644
--- a/quacker/quacker.pro
+++ b/quacker/quacker.pro
@@ -1,5 +1,5 @@
TEMPLATE = app
-VERSION = 0.99
+VERSION = 1.0
TARGET = Quackle
DEPENDPATH += .. ../quackleio
INCLUDEPATH += . ..
@@ -10,19 +10,18 @@ MOC_DIR = moc
#CONFIG += debug
CONFIG += release
+#Um, why is this necessary? I don't know. But if this isn't here,
+#qmake messes up resulting Visual Studio project files.
+CONFIG -= debug
+
debug {
OBJECTS_DIR = obj/debug
+ QMAKE_LIBDIR += ../lib/debug ../quackleio/lib/debug
}
release {
OBJECTS_DIR = obj/release
-}
-
-debug {
- QMAKE_LIBDIR += ../lib/debug ../quackleio/lib/debug
-}
-release {
- QMAKE_LIBDIR += ../lib/release ../quackleio/lib/release
+ QMAKE_LIBDIR += ../lib/release ../quackleio/lib/release
}
win32:!win32-g++ {
@@ -32,6 +31,8 @@ win32:!win32-g++ {
}
macx:LIBS += -framework CoreFoundation
+QMAKE_CXXFLAGS += -std=c++11
+
# Input
HEADERS += *.h
SOURCES += *.cpp
diff --git a/quacker/settings.cpp b/quacker/settings.cpp
index 301608e..e22a29e 100644
--- a/quacker/settings.cpp
+++ b/quacker/settings.cpp
@@ -45,6 +45,7 @@
#include "boardsetupdialog.h"
#include "customqsettings.h"
#include "graphicalboard.h"
+#include "lexicondialog.h"
Settings *Settings::m_self = 0;
Settings *Settings::self()
@@ -80,17 +81,20 @@ Settings::Settings(QWidget *parent)
#endif
if (QFile::exists("data"))
- m_dataDir = "data";
+ m_appDataDir = "data";
else if (QFile::exists("../data"))
- m_dataDir = "../data";
+ m_appDataDir = "../data";
else if (QFile::exists("Quackle.app/Contents/data"))
- m_dataDir = "Quackle.app/Contents/data";
+ m_appDataDir = "Quackle.app/Contents/data";
else
{
if (!directory.cd("data") || !directory.cd("../data"))
QMessageBox::critical(0, tr("Error Initializing Data Files - Quacker"), tr("<p>Could not open data directory. Quackle will be useless. Try running the quacker executable with quackle/quacker/ as the current directory.</p>"));
- m_dataDir = directory.absolutePath();
+ m_appDataDir = directory.absolutePath();
}
+ m_userDataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
+ QDir qdir(m_userDataDir);
+ qdir.mkpath("lexica");
}
void Settings::createGUI()
@@ -98,93 +102,88 @@ void Settings::createGUI()
if (m_lexiconNameCombo != 0)
return;
- QVBoxLayout *vlayout = new QVBoxLayout(this);
+ QGridLayout *layout = new QGridLayout(this);
m_lexiconNameCombo = new QComboBox;
connect(m_lexiconNameCombo, SIGNAL(activated(const QString &)), this, SLOT(lexiconChanged(const QString &)));
- QStringList items;
- populateListFromFilenames(items, m_dataDir + "/lexica");
- m_lexiconNameCombo->addItems(items);
+ populateComboFromFilenames(m_lexiconNameCombo, "lexica", ".dawg", "lexicon");
- QLabel *cswText = new QLabel(tr("The WESPA wordlist (CSW12) is copyright Harper Collins 2011."));
-
- QHBoxLayout *lexiconLayout = new QHBoxLayout;
QLabel *lexiconNameLabel = new QLabel(tr("&Lexicon:"));
lexiconNameLabel->setBuddy(m_lexiconNameCombo);
-
- lexiconLayout->addWidget(lexiconNameLabel);
- lexiconLayout->addWidget(m_lexiconNameCombo);
+ m_editLexicon = new QPushButton(tr("Edit..."));
+ m_editLexicon->setMaximumWidth(60);
+ connect(m_editLexicon, SIGNAL(clicked()), this, SLOT(editLexicon()));
m_alphabetNameCombo = new QComboBox;
connect(m_alphabetNameCombo, SIGNAL(activated(const QString &)), this, SLOT(alphabetChanged(const QString &)));
- QStringList alphabetItems;
- populateListFromFilenames(alphabetItems, m_dataDir + "/alphabets");
- m_alphabetNameCombo->addItems(alphabetItems);
+ populateComboFromFilenames(m_alphabetNameCombo, "alphabets", ".quackle_alphabet", "");
- QHBoxLayout *alphabetLayout = new QHBoxLayout;
QLabel *alphabetNameLabel = new QLabel(tr("&Alphabet:"));
alphabetNameLabel->setBuddy(m_alphabetNameCombo);
-
- alphabetLayout->addWidget(alphabetNameLabel);
- alphabetLayout->addWidget(m_alphabetNameCombo);
+ m_editAlphabet = new QPushButton(tr("Edit..."));
+ m_editAlphabet->setMaximumWidth(60);
+ connect(m_editAlphabet, SIGNAL(clicked()), this, SLOT(editAlphabet()));
m_themeNameCombo = new QComboBox;
connect(m_themeNameCombo, SIGNAL(activated(const QString &)), this, SLOT(themeChanged(const QString &)));
- QStringList themeItems;
- populateListFromFilenames(themeItems, m_dataDir + "/themes");
- m_themeNameCombo->addItems(themeItems);
+ populateComboFromFilenames(m_themeNameCombo, "themes", ".ini", "");
- QHBoxLayout *themeLayout = new QHBoxLayout;
QLabel *themeNameLabel = new QLabel(tr("&Theme:"));
themeNameLabel->setBuddy(m_themeNameCombo);
+ m_editTheme = new QPushButton(tr("Edit..."));
+ m_editTheme->setMaximumWidth(60);
+ connect(m_editTheme, SIGNAL(clicked()), this, SLOT(editTheme()));
- themeLayout->addWidget(themeNameLabel);
- themeLayout->addWidget(m_themeNameCombo);
-
- m_boardNameCombo = new QComboBox();
+ m_boardNameCombo = new QComboBox;
connect(m_boardNameCombo, SIGNAL(activated(const QString &)), this, SLOT(boardChanged(const QString &)));
- m_addBoard = new QPushButton(tr("Add Board"));
- connect(m_addBoard, SIGNAL(clicked()), this, SLOT(addBoard()));
+ populateComboFromFilenames(m_boardNameCombo, "boards", "", "board");
- m_editBoard = new QPushButton(tr("&Edit Board"));
+ QLabel *boardNameLabel = new QLabel(tr("&Board:"));
+ boardNameLabel->setBuddy(m_boardNameCombo);
+ m_editBoard = new QPushButton(tr("Edit..."));
+ m_editBoard->setMaximumWidth(60);
connect(m_editBoard, SIGNAL(clicked()), this, SLOT(editBoard()));
- m_deleteBoard = new QPushButton(tr("&Delete Board"));
- connect(m_deleteBoard, SIGNAL(clicked()), this, SLOT(deleteBoard()));
+ m_copyrightLabel = new QLabel();
- loadBoardNameCombo();
+ layout->addWidget(lexiconNameLabel, 0, 0, Qt::AlignRight);
+ layout->addWidget(m_lexiconNameCombo, 0, 1);
+ layout->addWidget(m_editLexicon, 0, 2);
+ layout->addWidget(alphabetNameLabel, 1, 0, Qt::AlignRight);
+ layout->addWidget(m_alphabetNameCombo, 1, 1);
+ // layout->addWidget(m_editAlphabet, 1, 2);
+ layout->addWidget(themeNameLabel, 2, 0, Qt::AlignRight);
+ layout->addWidget(m_themeNameCombo, 2, 1);
+ // layout->addWidget(m_editTheme, 2, 2);
+ layout->addWidget(boardNameLabel, 3, 0, Qt::AlignRight);
+ layout->addWidget(m_boardNameCombo, 3, 1);
+ layout->addWidget(m_editBoard, 3, 2);
+ layout->addWidget(m_copyrightLabel, 4, 0, 1, -1, Qt::AlignTop);
- QGroupBox *boardGroup = new QGroupBox("Game Board Definitions");
- QGridLayout *boardLayout = new QGridLayout(boardGroup);
- QLabel *boardNameLabel = new QLabel(tr("&Board:"));
- boardNameLabel->setBuddy(m_boardNameCombo);
+ layout->setColumnMinimumWidth(3, 0);
+ layout->setColumnStretch(3, 1);
+ layout->setRowMinimumHeight(4, 0);
+ layout->setRowStretch(4, 1);
- boardLayout->addWidget(boardNameLabel, 0, 0);
- boardLayout->addWidget(m_boardNameCombo, 0, 1, 1, -1);
- boardLayout->addWidget(m_addBoard, 1, 0);
- boardLayout->addWidget(m_editBoard, 1, 1);
- boardLayout->addWidget(m_deleteBoard, 1, 2);
-
- vlayout->addWidget(cswText);
- vlayout->addLayout(lexiconLayout);
- vlayout->addLayout(alphabetLayout);
- vlayout->addLayout(themeLayout);
- vlayout->addWidget(boardGroup);
- vlayout->addStretch();
load();
}
void Settings::load()
{
- m_lexiconNameCombo->setCurrentIndex(m_lexiconNameCombo->findText(QuackleIO::Util::stdStringToQString(QUACKLE_LEXICON_PARAMETERS->lexiconName())));
- m_alphabetNameCombo->setCurrentIndex(m_alphabetNameCombo->findText(QuackleIO::Util::stdStringToQString(QUACKLE_ALPHABET_PARAMETERS->alphabetName())));
+ m_lexiconNameCombo->setCurrentIndex(m_lexiconNameCombo->findText(QString::fromUtf8(QUACKLE_LEXICON_PARAMETERS->lexiconName().c_str())));
+ if (m_lexiconNameCombo->currentIndex() == -1)
+ m_lexiconNameCombo->setCurrentIndex(m_lexiconNameCombo->findText(QString::fromUtf8(QUACKLE_LEXICON_PARAMETERS->lexiconName().c_str()) + "*"));
+ m_lastGoodLexiconValue = m_lexiconNameCombo->currentIndex();
+ m_alphabetNameCombo->setCurrentIndex(m_alphabetNameCombo->findText(QString::fromUtf8(QUACKLE_ALPHABET_PARAMETERS->alphabetName().c_str())));
m_themeNameCombo->setCurrentIndex(m_themeNameCombo->findText(m_themeName));
m_boardNameCombo->setCurrentIndex(m_boardNameCombo->findText(QuackleIO::Util::uvStringToQString(QUACKLE_BOARD_PARAMETERS->name())));
+ m_lastGoodBoardValue = m_boardNameCombo->currentIndex();
+ m_copyrightLabel->setText(QString::fromUtf8(QUACKLE_LEXICON_PARAMETERS->copyrightString().c_str()));
}
void Settings::preInitialize()
@@ -198,7 +197,8 @@ void Settings::initialize()
CustomQSettings settings;
QUACKLE_DATAMANAGER->setBackupLexicon("twl06");
- QUACKLE_DATAMANAGER->setDataDirectory(m_dataDir.toStdString());
+ QUACKLE_DATAMANAGER->setAppDataDirectory(m_appDataDir.toStdString());
+ QUACKLE_DATAMANAGER->setUserDataDirectory(m_userDataDir.toStdString());
QString lexiconName = settings.value("quackle/settings/lexicon-name", QString("twl06")).toString();
@@ -206,50 +206,98 @@ void Settings::initialize()
if (lexiconName == "cswfeb07")
lexiconName = "cswapr07";
- setQuackleToUseLexiconName(QuackleIO::Util::qstringToStdString(lexiconName));
- setQuackleToUseAlphabetName(QuackleIO::Util::qstringToStdString(settings.value("quackle/settings/alphabet-name", QString("english")).toString()));
+ setQuackleToUseLexiconName(lexiconName);
+ setQuackleToUseAlphabetName(settings.value("quackle/settings/alphabet-name", QString("english")).toString());
setQuackleToUseThemeName(settings.value("quackle/settings/theme-name", QString("traditional")).toString());
setQuackleToUseBoardName(settings.value("quackle/settings/board-name", QString("")).toString());
}
-void Settings::setQuackleToUseLexiconName(const string &lexiconName)
+void Settings::buildGaddag(const string &filename)
+{
+ GaddagFactory factory((UVString()));
+ Quackle::LetterString word;
+
+ pushIndex(factory, word, 1);
+ factory.generate();
+ factory.writeIndex(filename);
+}
+
+void Settings::pushIndex(GaddagFactory &factory, Quackle::LetterString &word, int index)
{
- if (QUACKLE_LEXICON_PARAMETERS->lexiconName() != lexiconName)
+ unsigned int p;
+ Quackle::Letter letter;
+ bool t;
+ bool lastchild;
+ bool british;
+ int playability;
+
+ do
{
- QUACKLE_LEXICON_PARAMETERS->setLexiconName(lexiconName);
+ QUACKLE_LEXICON_PARAMETERS->dawgAt(index, p, letter, t, lastchild, british, playability);
+ word.push_back(letter);
+ if (t)
+ factory.pushWord(word);
+ if (p)
+ pushIndex(factory, word, p);
+ index++;
+ word.pop_back();
+ } while (!lastchild);
+}
- string gaddagFile = Quackle::LexiconParameters::findDictionaryFile(lexiconName + ".gaddag");
- if (gaddagFile.empty())
- {
- UVcout << "Gaddag for lexicon '" << lexiconName << "' does not exist." << endl;
- QUACKLE_LEXICON_PARAMETERS->unloadGaddag();
- }
- else
- QUACKLE_LEXICON_PARAMETERS->loadGaddag(gaddagFile);
+void Settings::setQuackleToUseLexiconName(const QString &lexiconName)
+{
+ string lexiconNameStr = lexiconName.toStdString();
+ if (QUACKLE_LEXICON_PARAMETERS->lexiconName() != lexiconNameStr)
+ {
+ QUACKLE_LEXICON_PARAMETERS->setLexiconName(lexiconNameStr);
- string dawgFile = Quackle::LexiconParameters::findDictionaryFile(lexiconName + ".dawg");
+ string dawgFile = Quackle::LexiconParameters::findDictionaryFile(lexiconNameStr + ".dawg");
if (dawgFile.empty())
{
- UVcout << "Dawg for lexicon '" << lexiconName << "' does not exist." << endl;
+ UVcout << "Dawg for lexicon '" << lexiconNameStr << "' does not exist." << endl;
QUACKLE_LEXICON_PARAMETERS->unloadDawg();
}
else
QUACKLE_LEXICON_PARAMETERS->loadDawg(dawgFile);
- QUACKLE_STRATEGY_PARAMETERS->initialize(lexiconName);
+ if (!QUACKLE_LEXICON_PARAMETERS->hasDawg())
+ {
+ QUACKLE_LEXICON_PARAMETERS->unloadGaddag();
+ return;
+ }
+
+ string gaddagFile = Quackle::LexiconParameters::findDictionaryFile(lexiconNameStr + ".gaddag");
+ if (gaddagFile.empty())
+ {
+ UVcout << "Gaddag for lexicon '" << lexiconNameStr << "' does not exist." << endl;
+ QUACKLE_LEXICON_PARAMETERS->unloadGaddag();
+ }
+ else
+ QUACKLE_LEXICON_PARAMETERS->loadGaddag(gaddagFile);
+
+ // if (!QUACKLE_LEXICON_PARAMETERS->hasGaddag())
+ // {
+ // gaddagFile = QUACKLE_DATAMANAGER->makeDataFilename("lexica", lexiconNameStr + ".gaddag", true);
+ // buildGaddag(gaddagFile);
+ // QUACKLE_LEXICON_PARAMETERS->loadGaddag(gaddagFile);
+ // }
+
+ QUACKLE_STRATEGY_PARAMETERS->initialize(lexiconNameStr);
+ m_copyrightLabel->setText(QString::fromUtf8(QUACKLE_LEXICON_PARAMETERS->copyrightString().c_str()));
}
}
-void Settings::setQuackleToUseAlphabetName(const string &alphabetName)
+void Settings::setQuackleToUseAlphabetName(const QString &alphabetName)
{
- if (QUACKLE_ALPHABET_PARAMETERS->alphabetName() != alphabetName)
+ string alphabetNameStr = alphabetName.toStdString();
+ if (QUACKLE_ALPHABET_PARAMETERS->alphabetName() != alphabetNameStr)
{
- QString alphabetFile = QuackleIO::Util::stdStringToQString(Quackle::AlphabetParameters::findAlphabetFile(alphabetName + ".quackle_alphabet"));
+ QString alphabetFileStr = QuackleIO::Util::stdStringToQString(Quackle::AlphabetParameters::findAlphabetFile(alphabetNameStr));
QuackleIO::FlexibleAlphabetParameters *flexure = new QuackleIO::FlexibleAlphabetParameters;
- flexure->setAlphabetName(alphabetName);
- if (flexure->load(alphabetFile))
+ flexure->setAlphabetName(alphabetNameStr);
+ if (flexure->load(alphabetFileStr))
{
if (flexure->length() != QUACKLE_ALPHABET_PARAMETERS->length() && QUACKLE_ALPHABET_PARAMETERS->alphabetName() != "default")
{
@@ -269,11 +317,13 @@ void Settings::setQuackleToUseAlphabetName(const string &alphabetName)
void Settings::setQuackleToUseThemeName(const QString &themeName)
{
m_themeName = themeName;
- QString themeFile = m_dataDir + "/themes/" + themeName + ".ini";
+ QString themeFile = m_userDataDir + "/themes/" + themeName + ".ini";
+ if (!QFile::exists(themeFile))
+ themeFile = m_appDataDir + "/themes/" + themeName + ".ini";
if (!QFile::exists(themeFile))
{
m_themeName = "traditional";
- themeFile = m_dataDir + "/themes/traditional.ini";
+ themeFile = m_appDataDir + "/themes/traditional.ini";
}
PixmapCacher::self()->readTheme(themeFile);
}
@@ -300,19 +350,34 @@ void Settings::setQuackleToUseBoardName(const QString &boardName)
void Settings::lexiconChanged(const QString &lexiconName)
{
- string lexiconNameString = QuackleIO::Util::qstringToStdString(lexiconName);
- setQuackleToUseLexiconName(lexiconNameString);
+ QString lexicon = lexiconName;
+ if (lexicon.endsWith("*"))
+ lexicon.truncate(lexicon.size() - 1);
+ if (m_lexiconNameCombo->currentIndex() == m_lexiconNameCombo->count() - 1)
+ {
+ editLexicon();
+ if (m_lexiconNameCombo->currentIndex() == m_lexiconNameCombo->count() - 1 &&
+ m_lexiconNameCombo->currentIndex() != 0)
+ m_lexiconNameCombo->setCurrentIndex(m_lastGoodLexiconValue);
+ return;
+ }
+ setQuackleToUseLexiconName(lexicon);
+ m_lastGoodLexiconValue = m_lexiconNameCombo->currentIndex();
CustomQSettings settings;
- settings.setValue("quackle/settings/lexicon-name", lexiconName);
+ settings.setValue("quackle/settings/lexicon-name", lexicon);
emit refreshViews();
}
void Settings::alphabetChanged(const QString &alphabetName)
{
- string alphabetNameString = QuackleIO::Util::qstringToStdString(alphabetName);
- setQuackleToUseAlphabetName(alphabetNameString);
+ if (m_alphabetNameCombo->currentIndex() == m_alphabetNameCombo->count() - 1)
+ {
+ editAlphabet();
+ return;
+ }
+ setQuackleToUseAlphabetName(alphabetName);
CustomQSettings settings;
settings.setValue("quackle/settings/alphabet-name", alphabetName);
@@ -322,6 +387,11 @@ void Settings::alphabetChanged(const QString &alphabetName)
void Settings::themeChanged(const QString &themeName)
{
+ if (m_themeNameCombo->currentIndex() == m_themeNameCombo->count() - 1)
+ {
+ editTheme();
+ return;
+ }
setQuackleToUseThemeName(themeName);
CustomQSettings settings;
@@ -332,6 +402,14 @@ void Settings::themeChanged(const QString &themeName)
void Settings::boardChanged(const QString &boardName)
{
+ if (m_boardNameCombo->currentIndex() == m_boardNameCombo->count() - 1)
+ {
+ addBoard();
+ if (m_boardNameCombo->currentIndex() == m_boardNameCombo->count() - 1 &&
+ m_boardNameCombo->currentIndex() != 0)
+ m_boardNameCombo->setCurrentIndex(m_lastGoodBoardValue);
+ return;
+ }
CustomQSettings settings;
settings.setValue("quackle/settings/board-name", boardName);
@@ -358,6 +436,7 @@ void Settings::addBoard()
(const uchar *)boardParameterStream.str().data(),
boardParameterStream.str().size());
settings.setValue(boardName, QVariant(boardParameterBytes));
+ m_boardNameCombo->setCurrentIndex(-1);
boardChanged(boardName);
}
else
@@ -391,35 +470,12 @@ void Settings::editBoard()
boardChanged(newBoardName);
}
PixmapCacher::self()->invalidate();
-}
-
-void Settings::deleteBoard()
-{
- int oldIndex = m_boardNameCombo->currentIndex();
- QString boardName = m_boardNameCombo->currentText();
- QString message = "Do you really want to delete the game board \"";
- message += boardName;
- message += "\"?";
- if (QMessageBox::warning(NULL, QString("Confirm Deletion"), message,
- QMessageBox::Yes | QMessageBox::Default,
- QMessageBox::No | QMessageBox::Escape) == QMessageBox::Yes)
- {
- CustomQSettings settings;
- settings.beginGroup("quackle/boardparameters");
- settings.remove(boardName);
- loadBoardNameCombo();
- if (oldIndex != 0)
- oldIndex--;
- m_boardNameCombo->setCurrentIndex(oldIndex);
- boardChanged(m_boardNameCombo->currentText());
- }
+ loadBoardNameCombo();
+ emit refreshViews();
}
void Settings::loadBoardNameCombo()
{
- if (m_lexiconNameCombo == 0)
- return;
-
while (m_boardNameCombo->count() > 0)
m_boardNameCombo->removeItem(0);
@@ -428,26 +484,100 @@ void Settings::loadBoardNameCombo()
QStringList boardNames = settings.childKeys();
boardNames.sort();
m_boardNameCombo->addItems(boardNames);
+ m_boardNameCombo->addItem("Add new board...");
settings.endGroup();
QString currentItem = settings.value("quackle/settings/board-name", QString("")).toString();
- m_boardNameCombo->setCurrentIndex(m_boardNameCombo->findText(currentItem));
+ int currentItemIndex = m_boardNameCombo->findText(currentItem);
+ if (m_boardNameCombo->count() > 0 && currentItemIndex < 0)
+ currentItemIndex = 0;
+ m_boardNameCombo->setCurrentIndex(currentItemIndex);
+}
+
+void Settings::editLexicon()
+{
+ QString name = m_lexiconNameCombo->currentText();
+ if (name.endsWith("*"))
+ name.truncate(name.size() - 1);
+ if (m_lexiconNameCombo->currentIndex() == m_lexiconNameCombo->count() - 1)
+ name = "";
+ LexiconDialog dialog(this, name);
+ if (dialog.exec())
+ {
+ populateComboFromFilenames(m_lexiconNameCombo, "lexica", ".dawg", "lexicon");
+ qApp->processEvents();
+ if (dialog.itemWasDeleted())
+ {
+ m_lexiconNameCombo->setCurrentIndex(m_lexiconNameCombo->findText(name));
+ QUACKLE_LEXICON_PARAMETERS->setLexiconName(""); // force lexicon to reload
+ QUACKLE_LEXICON_PARAMETERS->unloadAll();
+ if (m_lexiconNameCombo->currentIndex() != -1)
+ setQuackleToUseLexiconName(name);
+ }
+ else if (!dialog.lexiconName().isEmpty())
+ {
+ QUACKLE_LEXICON_PARAMETERS->setLexiconName(""); // force lexicon to reload
+ QUACKLE_LEXICON_PARAMETERS->unloadAll();
+ setQuackleToUseLexiconName(dialog.lexiconName());
+ m_lexiconNameCombo->setCurrentIndex(m_lexiconNameCombo->findText(name + "*"));
+ }
+ load();
+ }
+}
- m_editBoard->setEnabled(boardNames.count() > 0);
- m_deleteBoard->setEnabled(boardNames.count() > 0);
+void Settings::editAlphabet()
+{
+#if 0
+ QString name = m_alphabetNameCombo->currentText();
+ if (m_alphabetNameCombo->currentIndex() == m_alphabetNameCombo->count() - 1)
+ name = "";
+ AlphabetDialog dialog(this);
+ if (dialog.exec())
+ {
+ populateComboFromFilenames(m_alphabetNameCombo, "alphabets", ".quackle_alphabet", "alphabet");
+ load();
+ }
+#endif // 0
+}
+
+void Settings::editTheme()
+{
+#if 0
+ QString name = m_themeNameCombo->currentText();
+ if (m_themeNameCombo->currentIndex() == m_themeNameCombo->count() - 1)
+ name = "";
+ ThemeDialog dialog(this);
+ if (dialog.exec())
+ {
+ populateThemeFromFilenames(m_themeNameCombo, "themes", "theme");
+ load();
+ }
+#endif // 0
}
-void Settings::populateListFromFilenames(QStringList& list, const QString &path)
+void Settings::populateComboFromFilenames(QComboBox* combo, const QString &path, const QString &extension, const QString &label)
{
- QDir dir(path);
- QStringList fileList = dir.entryList(QDir::Files | QDir::Readable, QDir::Name);
- QStringListIterator i(fileList);
+ while (combo->count() > 0)
+ combo->removeItem(0);
+
+ QStringList fileList;
+ QDir dir(self()->m_appDataDir);
+ if (dir.cd(path))
+ fileList << dir.entryList(QDir::Files | QDir::Readable, QDir::Name);
+ dir = QDir(self()->m_userDataDir);
+ if (dir.cd(path))
+ fileList << dir.entryList(QDir::Files | QDir::Readable, QDir::Name);
+
+ QStringList::iterator i;
QString fileName;
+ QStringList list;
int periodPos;
- while (i.hasNext())
+ for (i = fileList.begin(); i != fileList.end(); ++i)
{
- fileName = i.next();
+ fileName = *i;
+ if (!fileName.endsWith(extension))
+ continue;
periodPos = fileName.indexOf('.');
if (periodPos)
{
@@ -455,5 +585,21 @@ void Settings::populateListFromFilenames(QStringList& list, const QString &path)
list << fileName;
}
}
- list.removeDuplicates();
+
+ for (i = list.begin(); i != list.end(); ++i)
+ {
+ for (QStringList::iterator j = i + 1; j != list.end(); ++j)
+ {
+ if (*i == *j)
+ {
+ *i = *i + "*";
+ list.erase(j);
+ break;
+ }
+ }
+ }
+
+ combo->addItems(list);
+ if (label.size() > 0)
+ combo->addItem(QString(tr("Add new ")).append(path).append("..."));
}
diff --git a/quacker/settings.h b/quacker/settings.h
index 785b726..ef3449e 100644
--- a/quacker/settings.h
+++ b/quacker/settings.h
@@ -24,9 +24,12 @@
#include <QWidget>
#include <QSettings>
+#include "quackleio/gaddagfactory.h"
+
class QComboBox;
class QCheckBox;
class QPushButton;
+class QLabel;
using namespace std;
@@ -39,6 +42,9 @@ public:
static Settings *self();
+ // load up an item list based on a list of filenames
+ static void populateComboFromFilenames(QComboBox* combo, const QString &path, const QString &extension, const QString &label);
+
signals:
void refreshViews();
@@ -64,10 +70,13 @@ protected slots:
void addBoard();
void editBoard();
- void deleteBoard();
- void setQuackleToUseLexiconName(const string &lexiconName);
- void setQuackleToUseAlphabetName(const string &alphabetName);
+ void editLexicon();
+ void editAlphabet();
+ void editTheme();
+
+ void setQuackleToUseLexiconName(const QString &lexiconName);
+ void setQuackleToUseAlphabetName(const QString &alphabetName);
void setQuackleToUseThemeName(const QString &themeName);
void setQuackleToUseBoardName(const QString &lexiconName);
@@ -76,20 +85,25 @@ protected:
QComboBox *m_alphabetNameCombo;
QComboBox *m_themeNameCombo;
QComboBox *m_boardNameCombo;
- QPushButton *m_addBoard;
+ QPushButton *m_editLexicon;
+ QPushButton *m_editAlphabet;
+ QPushButton *m_editTheme;
QPushButton *m_editBoard;
- QPushButton *m_deleteBoard;
- QString m_dataDir;
+ QLabel *m_copyrightLabel;
+ QString m_appDataDir;
+ QString m_userDataDir;
QString m_themeName;
private:
// populate the popup based on what's in QSettings
void loadBoardNameCombo();
- // load up an item list based on a list of filenames
- void populateListFromFilenames(QStringList& list, const QString &path);
-
+ void buildGaddag(const string &filename);
+ void pushIndex(GaddagFactory &factory, Quackle::LetterString &word, int index);
+
static Settings *m_self;
+ int m_lastGoodLexiconValue;
+ int m_lastGoodBoardValue;
};
#endif