mainwindow.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /*****************************************************************************
  2. * mainwindow.cpp - QStarDict, a dictionary application for learning foreign *
  3. * languages *
  4. * Copyright (C) 2007-2023 Alexander Rodin *
  5. * *
  6. * This program is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 2 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License along *
  17. * with this program; if not, write to the Free Software Foundation, Inc., *
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
  19. *****************************************************************************/
  20. #include "mainwindow.h"
  21. #include <QApplication>
  22. #include <QCloseEvent>
  23. #include <QDesktopServices>
  24. #include <QDir>
  25. #include <QFile>
  26. #include <QFileDialog>
  27. #include <QListWidgetItem>
  28. #include <QKeyEvent>
  29. #include <QMenu>
  30. #include <QMessageBox>
  31. #include <QSettings>
  32. #include <QTextStream>
  33. #include <QTimerEvent>
  34. #include <QToolBar>
  35. #include <QKeySequence>
  36. #include <QShortcut>
  37. #include "dictcore.h"
  38. #include "application.h"
  39. #include "help.h"
  40. #include "popupwindow.h"
  41. #include "settingsdialog.h"
  42. #include "qxt/qxtglobalshortcut.h"
  43. #include <QDebug>
  44. namespace QStarDict
  45. {
  46. MainWindow::MainWindow(QWidget *parent, bool background) :
  47. QMainWindow(parent),
  48. m_instantSearch(false),
  49. m_queryTimer(0),
  50. m_background(background)
  51. {
  52. setupUi(this);
  53. m_dict = 0;
  54. translationView->setDict(m_dict);
  55. menu_File->insertActions(actionQuit, translationView->toolBar()->actions());
  56. menu_Options->insertAction(menu_Options->actions().first(), wordsListDock->toggleViewAction());
  57. createConnections();
  58. loadSettings();
  59. showIntro();
  60. }
  61. MainWindow::~MainWindow()
  62. {
  63. saveSettings();
  64. }
  65. void MainWindow::showTranslation(const QString &text)
  66. {
  67. searchBox->setText(text);
  68. on_queryButton_clicked();
  69. translationView->setFocus();
  70. }
  71. void MainWindow::createConnections()
  72. {
  73. Application * const app = Application::instance();
  74. connect(actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
  75. connect(actionQuit, SIGNAL(triggered()), qApp, SLOT(quit()));
  76. actionScan->setChecked(app->popupWindow()->isScan());
  77. connect(actionScan, SIGNAL(toggled(bool)),
  78. app->popupWindow(), SLOT(setScan(bool)));
  79. connect(app->popupWindow(), SIGNAL(scanChanged(bool)),
  80. actionScan, SLOT(setChecked(bool)));
  81. connect(wordsList, SIGNAL(itemActivated(QListWidgetItem*)),
  82. SLOT(wordsListItemActivated(QListWidgetItem*)));
  83. connect(wordsList, SIGNAL(itemClicked(QListWidgetItem*)),
  84. SLOT(wordsListItemActivated(QListWidgetItem*)));
  85. connect(translationView, SIGNAL(wordTranslated(const QString&)),
  86. SLOT(wordTranslated(const QString&)));
  87. connect(app->popupShortcut(),
  88. SIGNAL(activated()),
  89. app->popupWindow(),
  90. SLOT(showClipboardTranslation()));
  91. connect(app->switchScanningShortcut(),
  92. &QxtGlobalShortcut::activated,
  93. [=]() {
  94. app->popupWindow()->setScan(! app->popupWindow()->isScan());
  95. });
  96. #ifndef Q_WS_WINDOWS
  97. new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this, SLOT(close()));
  98. #endif
  99. }
  100. void MainWindow::loadSettings()
  101. {
  102. Application * const app = Application::instance();
  103. QSettings config;
  104. restoreGeometry(config.value("MainWindow/geometry", QByteArray()).toByteArray());
  105. restoreState(config.value("MainWindow/state", QByteArray()).toByteArray());
  106. setVisible(! m_background && config.value("MainWindow/visible", true).toBool());
  107. setQuitOnClose(config.value("MainWindow/quitOnClose", false).toBool());
  108. if (isHidden() && quitOnClose())
  109. show();
  110. wordsListDock->setFloating(config.value("MainWindow/wordsListDock/floating", wordsListDock->isFloating()).toBool());
  111. wordsListDock->setGeometry(config.value("MainWindow/wordsListDock/geometry", wordsListDock->geometry()).toRect());
  112. setInstantSearch(config.value("MainWindow/instantSearch", true).toBool());
  113. setDefaultStyleSheet(config.value("MainWindow/defaultStyleSheet", defaultStyleSheet()).toString());
  114. setShowLinks(config.value("MainWindow/showLinks", showLinks()).toBool());
  115. setShowLinksModifierKey(config.value("MainWindow/showLinksModifierKey", showLinksModifierKey()).toInt());
  116. setShowIpaPronouncers(config.value("MainWindow/showIpaPronouncers", showIpaPronouncers()).toBool());
  117. app->popupShortcut()->setShortcut(QKeySequence(
  118. config.value("MainWindow/popupShortcutString", tr("Shift+Ctrl+F")).toString()));
  119. app->popupShortcut()->setEnabled(
  120. config.value("MainWindow/popupShortcutEnabled", false).toBool());
  121. app->switchScanningShortcut()->setShortcut(QKeySequence(
  122. config.value("MainWindow/switchScanningShortcutString", tr("Shift+Ctrl+S")).toString()));
  123. app->switchScanningShortcut()->setEnabled(
  124. config.value("MainWindow/switchScanningShortcutEnabled", true).toBool());
  125. }
  126. void MainWindow::showIntro()
  127. {
  128. setWindowTitle(tr("QStarDict"));
  129. translationView->showIntro();
  130. wordsList->clear();
  131. }
  132. void MainWindow::saveSettings()
  133. {
  134. QSettings config;
  135. config.setValue("MainWindow/geometry", saveGeometry());
  136. config.setValue("MainWindow/state", saveState());
  137. // if "background" option was explicitly set, we don't want to save the state for the next run
  138. if (!m_background)
  139. config.setValue("MainWindow/visible", isVisible());
  140. config.setValue("MainWindow/quitOnClose", quitOnClose());
  141. config.setValue("MainWindow/wordsListDock/floating", wordsListDock->isFloating());
  142. config.setValue("MainWindow/wordsListDock/geometry", wordsListDock->geometry());
  143. config.setValue("MainWindow/instantSearch", m_instantSearch);
  144. config.setValue("MainWindow/defaultStyleSheet", defaultStyleSheet());
  145. config.setValue("MainWindow/showLinks", showLinks());
  146. config.setValue("MainWindow/showLinksModifierKey", showLinksModifierKey());
  147. config.setValue("MainWindow/showIpaPronouncers", showIpaPronouncers());
  148. Application * const app = Application::instance();
  149. config.setValue("MainWindow/popupShortcutString",
  150. app->popupShortcut()->shortcut().toString());
  151. config.setValue("MainWindow/popupShortcutEnabled",
  152. app->popupShortcut()->isEnabled());
  153. config.setValue("MainWindow/switchScanningShortcutString",
  154. app->switchScanningShortcut()->shortcut().toString());
  155. config.setValue("MainWindow/switchScanningShortcutEnabled",
  156. app->switchScanningShortcut()->isEnabled());
  157. }
  158. void MainWindow::on_actionAbout_triggered()
  159. {
  160. QMessageBox::about(this,
  161. tr("About QStarDict"),
  162. tr("<b>QStarDict %1 </b> - Qt version of StarDict<br>").arg(QSTARDICT_VERSION) +
  163. tr("Copyright (C) 2007-2023 Alexander Rodin "
  164. "<a href=\"http://qstardict.ylsoftware.com\">http://qstardict.ylsoftware.com</a>"));
  165. }
  166. void MainWindow::on_actionSettings_triggered()
  167. {
  168. SettingsDialog dialog(this);
  169. dialog.exec();
  170. }
  171. void MainWindow::on_actionHelp_triggered()
  172. {
  173. QDesktopServices::openUrl(Help::helpFilePath());
  174. }
  175. void MainWindow::on_queryButton_clicked()
  176. {
  177. if (searchBox->text().simplified().isEmpty())
  178. {
  179. showIntro();
  180. return;
  181. }
  182. wordsList->clear();
  183. wordsList->addItems(m_dict->findSimilarWords(searchBox->text()));
  184. translationView->translate(searchBox->text());
  185. }
  186. void MainWindow::reload()
  187. {
  188. wordsList->clear();
  189. wordsList->addItems(m_dict->findSimilarWords(translationView->translatedWord()));
  190. translationView->reload();
  191. }
  192. void MainWindow::queryEdited(const QString &)
  193. {
  194. if (m_queryTimer)
  195. killTimer(m_queryTimer);
  196. m_queryTimer = startTimer(200);
  197. }
  198. void MainWindow::timerEvent(QTimerEvent *event)
  199. {
  200. if (event->timerId() == m_queryTimer)
  201. {
  202. killTimer(m_queryTimer);
  203. m_queryTimer = 0;
  204. on_queryButton_clicked();
  205. }
  206. else
  207. QMainWindow::timerEvent(event);
  208. }
  209. void MainWindow::wordTranslated(const QString &word)
  210. {
  211. if (word.simplified().isEmpty())
  212. setWindowTitle(tr("QStarDict"));
  213. else
  214. setWindowTitle(tr("%1 - QStarDict").arg(word));
  215. if (m_queryTimer)
  216. {
  217. killTimer(m_queryTimer);
  218. m_queryTimer = 0;
  219. }
  220. }
  221. void MainWindow::wordsListItemActivated(QListWidgetItem *item)
  222. {
  223. searchBox->setText(item->text());
  224. translationView->translate(item->text());
  225. setWindowTitle(tr("%1 - QStarDict").arg(translationView->translatedWord()));
  226. }
  227. void MainWindow::setInstantSearch(bool instantSearch)
  228. {
  229. if (instantSearch == m_instantSearch)
  230. return;
  231. m_instantSearch = instantSearch;
  232. if (m_instantSearch)
  233. connect(searchBox, SIGNAL(textEdited(const QString&)), SLOT(queryEdited(const QString&)));
  234. else
  235. disconnect(searchBox, SIGNAL(textEdited(const QString&)), this, SLOT(queryEdited(const QString&)));
  236. }
  237. void MainWindow::setDict(DictCore *dict)
  238. {
  239. m_dict = dict;
  240. translationView->setDict(dict);
  241. }
  242. void MainWindow::keyPressEvent(QKeyEvent *event)
  243. {
  244. if (event->text().size() || event->key() == Qt::Key_Escape)
  245. {
  246. if (! searchBox->hasFocus())
  247. {
  248. searchBox->setText(event->text());
  249. searchBox->setFocus(Qt::OtherFocusReason);
  250. }
  251. if (event->key() == Qt::Key_Escape)
  252. {
  253. if (searchBox->text().isEmpty())
  254. close();
  255. else
  256. searchBox->clear();
  257. }
  258. }
  259. QMainWindow::keyPressEvent(event);
  260. }
  261. void MainWindow::closeEvent(QCloseEvent *event)
  262. {
  263. if (quitOnClose())
  264. Application::instance()->quit();
  265. QMainWindow::closeEvent(event);
  266. }
  267. }
  268. // vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab cindent textwidth=120 formatoptions=tc