1 /***********************************************************************
2  *
3  * Copyright (C) 2009, 2013, 2014 Graeme Gott <graeme@gottcode.org>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  ***********************************************************************/
19 
20 #include "definitions.h"
21 
22 #include "dictionary.h"
23 
24 #include <QDesktopServices>
25 #include <QDialogButtonBox>
26 #include <QHBoxLayout>
27 #include <QListWidget>
28 #include <QSettings>
29 #include <QSplitter>
30 #include <QTextBrowser>
31 #include <QVBoxLayout>
32 
Definitions(const WordList * wordlist,QWidget * parent)33 Definitions::Definitions(const WordList* wordlist, QWidget* parent)
34 : QDialog(parent) {
35 	QSettings settings;
36 	setWindowTitle(tr("Definitions"));
37 	setModal(true);
38 
39 	m_dictionary = new Dictionary(wordlist, this);
40 	connect(m_dictionary, &Dictionary::wordDefined, this, &Definitions::wordDefined);
41 
42 	m_contents = new QSplitter(this);
43 
44 	m_words = new QListWidget(m_contents);
45 	connect(m_words, &QListWidget::currentItemChanged, this, &Definitions::wordSelected);
46 	m_contents->addWidget(m_words);
47 	m_contents->setStretchFactor(0, 0);
48 	m_contents->setSizes(QList<int>() << settings.value("Definitions/Splitter", m_words->fontMetrics().averageCharWidth() * 12).toInt());
49 
50 	m_text = new QTextBrowser(m_contents);
51 	m_text->setReadOnly(true);
52 	m_text->setOpenLinks(false);
53 	connect(m_text, &QTextBrowser::anchorClicked, this, &Definitions::anchorClicked);
54 	m_contents->addWidget(m_text);
55 	m_contents->setStretchFactor(1, 1);
56 
57 	QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, this);
58 	connect(buttons, &QDialogButtonBox::rejected, this, &Definitions::reject);
59 
60 	QVBoxLayout* layout = new QVBoxLayout(this);
61 	layout->addWidget(m_contents);
62 	layout->addWidget(buttons);
63 
64 	resize(settings.value("Definitions/Size", QSize(500, 400)).toSize());
65 }
66 
67 //-----------------------------------------------------------------------------
68 
~Definitions()69 Definitions::~Definitions() {
70 	m_dictionary->wait();
71 }
72 
73 //-----------------------------------------------------------------------------
74 
clear()75 void Definitions::clear() {
76 	m_text->clear();
77 	m_word_table.clear();
78 	m_words->clear();
79 }
80 
81 //-----------------------------------------------------------------------------
82 
addWord(const QString & word)83 void Definitions::addWord(const QString& word) {
84 	QListWidgetItem* item = new QListWidgetItem(QString(word.length(), QChar('?')), m_words);
85 	m_word_table.insert(word, item);
86 	m_words->clearSelection();
87 	m_words->setCurrentRow(0);
88 }
89 
90 //-----------------------------------------------------------------------------
91 
solveWord(const QString & original_word,const QString & current_word)92 void Definitions::solveWord(const QString& original_word, const QString& current_word) {
93 	QListWidgetItem* item = m_word_table.value(original_word);
94 	if (item == 0) {
95 		return;
96 	}
97 	if (original_word != current_word) {
98 		m_word_table.remove(original_word);
99 		m_word_table.insert(current_word, item);
100 	}
101 	item->setText(current_word);
102 	m_words->sortItems();
103 	if (item == m_words->currentItem()) {
104 		wordSelected(item);
105 	}
106 }
107 
108 //-----------------------------------------------------------------------------
109 
selectWord(const QString & word)110 void Definitions::selectWord(const QString& word) {
111 	QListWidgetItem* item = m_word_table.value(word);
112 	if (item == 0) {
113 		item = m_words->item(0);
114 	}
115 	m_words->setCurrentItem(item);
116 	show();
117 }
118 
119 //-----------------------------------------------------------------------------
120 
hideEvent(QHideEvent * event)121 void Definitions::hideEvent(QHideEvent* event) {
122 	QSettings settings;
123 	settings.setValue("Definitions/Size", size());
124 	settings.setValue("Definitions/Splitter", m_contents->sizes().first());
125 	QDialog::hideEvent(event);
126 }
127 
128 //-----------------------------------------------------------------------------
129 
anchorClicked(const QUrl & link)130 void Definitions::anchorClicked(const QUrl& link) {
131 	QDesktopServices::openUrl(m_dictionary->url().resolved(link));
132 }
133 
134 //-----------------------------------------------------------------------------
135 
wordSelected(QListWidgetItem * item)136 void Definitions::wordSelected(QListWidgetItem* item) {
137 	if (item == 0) {
138 		m_text->clear();
139 		return;
140 	}
141 
142 	if (item->text().at(0) != QChar('?')) {
143 		QString definition = item->data(Qt::UserRole).toString();
144 		if (definition.isEmpty()) {
145 			definition = QString("<font color=\"#555\">%1</font>").arg(tr("Downloading definition..."));
146 			m_text->setHtml(definition);
147 			item->setData(Qt::UserRole, definition);
148 			m_dictionary->lookup(item->text());
149 		} else {
150 			m_text->setHtml(definition);
151 		}
152 	} else {
153 		m_text->setText(tr("Unsolved word"));
154 	}
155 }
156 
157 //-----------------------------------------------------------------------------
158 
wordDefined(const QString & word,const QString & definition)159 void Definitions::wordDefined(const QString& word, const QString& definition) {
160 	QListWidgetItem* item = m_word_table.value(word);
161 	if (item == 0) {
162 		return;
163 	}
164 	item->setData(Qt::UserRole, definition);
165 	if (item == m_words->currentItem()) {
166 		m_text->setHtml(definition);
167 	}
168 }
169