summaryrefslogtreecommitdiffstats
path: root/kdict/queryview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdict/queryview.cpp')
-rw-r--r--kdict/queryview.cpp618
1 files changed, 618 insertions, 0 deletions
diff --git a/kdict/queryview.cpp b/kdict/queryview.cpp
new file mode 100644
index 00000000..a2674d68
--- /dev/null
+++ b/kdict/queryview.cpp
@@ -0,0 +1,618 @@
+/* -------------------------------------------------------------
+
+ queryview.cpp (part of The KDE Dictionary Client)
+
+ Copyright (C) 2000-2001 Christian Gebauer <[email protected]>
+
+ This file is distributed under the Artistic License.
+ See LICENSE for details.
+
+ -------------------------------------------------------------
+
+ BrowseData data structure used for caching definitions
+ DictHTMLPart handling of middle mouse button clicks
+ QueryView widget that displays the definitions
+
+ ------------------------------------------------------------- */
+
+#include <qclipboard.h>
+#include <qtimer.h>
+
+#include <kfiledialog.h>
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+#include <kcursor.h>
+#include <kpopupmenu.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <khtml_events.h>
+#include <khtmlview.h>
+
+#include "actions.h"
+#include "options.h"
+#include "dict.h"
+#include "queryview.h"
+#include <kapplication.h>
+#include <kiconloader.h>
+
+
+//******** SaveHelper *******************************************
+
+QString SaveHelper::lastPath;
+
+SaveHelper::SaveHelper(const QString &saveName, const QString &filter, QWidget *parent)
+ : p_arent(parent), s_aveName(saveName), f_ilter(filter), file(0), tmpFile(0)
+{
+}
+
+
+SaveHelper::~SaveHelper()
+{
+ if (file) { // local filesystem, just close the file
+ delete file;
+ } else
+ if (tmpFile) { // network location, initiate transaction
+ tmpFile->close();
+ if (KIO::NetAccess::upload(tmpFile->name(),url, p_arent) == false)
+ KMessageBox::error(global->topLevel, i18n("Unable to save remote file."));
+ tmpFile->unlink(); // delete temp file
+ delete tmpFile;
+ }
+}
+
+
+QFile* SaveHelper::getFile(const QString &dialogTitle)
+{
+ url = KFileDialog::getSaveURL(lastPath+s_aveName,f_ilter,p_arent,dialogTitle);
+
+ if (url.isEmpty())
+ return 0;
+
+ lastPath = url.url(-1);
+ lastPath.truncate(lastPath.length()-url.fileName().length());
+
+ if (url.isLocalFile()) {
+ if (QFileInfo(url.path()).exists() &&
+ (KMessageBox::warningContinueCancel(global->topLevel,
+ i18n("A file named %1 already exists.\nDo you want to replace it?").arg(url.path()),
+ dialogTitle, i18n("&Replace")) != KMessageBox::Continue)) {
+ return 0;
+ }
+
+ file = new QFile(url.path());
+ if(!file->open(IO_WriteOnly)) {
+ KMessageBox::error(global->topLevel, i18n("Unable to save file."));
+ delete file;
+ file = 0;
+ }
+ return file;
+ } else {
+ tmpFile = new KTempFile();
+ if (tmpFile->status()!=0)
+ KMessageBox::error(global->topLevel, i18n("Unable to create temporary file.")); {
+ delete tmpFile;
+ tmpFile = 0;
+ return 0;
+ }
+ return tmpFile->file();
+ }
+}
+
+
+//**** BrowseData ****************************************************
+
+
+BrowseData::BrowseData(const QString &Nhtml, const QString &NqueryText)
+: html(Nhtml),queryText(NqueryText),xPos(0),yPos(0)
+{}
+
+
+//********* DictHTMLPart ******************************************
+
+DictHTMLPart::DictHTMLPart(QWidget *parentWidget, const char *widgetname)
+ : KHTMLPart(parentWidget,widgetname)
+{}
+
+
+DictHTMLPart::~DictHTMLPart()
+{}
+
+
+void DictHTMLPart::khtmlMouseReleaseEvent(khtml::MouseReleaseEvent *event)
+{
+ if (event->qmouseEvent()->button()==MidButton)
+ emit(middleButtonClicked());
+ else
+ KHTMLPart::khtmlMouseReleaseEvent(event);
+}
+
+
+//********* QueryView ******************************************
+
+
+QueryView::QueryView(QWidget *_parent)
+: QVBox( _parent), actBack(0L), actForward(0L), actQueryCombo(0L), browsePos(0), isRendering(false)
+{
+ browseList.setAutoDelete(true);
+
+ part=new DictHTMLPart(this);
+ part->setDNDEnabled(false);
+ part->setJScriptEnabled(false);
+ part->setJavaEnabled(false);
+ part->setURLCursor(KCursor::handCursor());
+ setFocusPolicy(QWidget::NoFocus);
+ connect(part, SIGNAL(completed()), SLOT(partCompleted()));
+ connect(part, SIGNAL(middleButtonClicked()), SLOT(middleButtonClicked()));
+ rightBtnMenu = new KPopupMenu(this);
+ connect(part,SIGNAL(popupMenu(const QString &, const QPoint &)),this,SLOT(buildPopupMenu(const QString &, const QPoint &)));
+ connect(part->browserExtension(),SIGNAL(openURLRequest(const KURL &,const KParts::URLArgs &)),
+ this,SLOT(slotURLRequest(const KURL &,const KParts::URLArgs &)));
+ connect(part->browserExtension(),SIGNAL(enableAction(const char *,bool)),this,SLOT(enableAction(const char *,bool)));
+ QTimer::singleShot( 0, this, SLOT(optionsChanged()) );
+ connect(interface,SIGNAL(resultReady(const QString &, const QString &)), SLOT(resultReady(const QString &, const QString &)));
+}
+
+
+QueryView::~QueryView()
+{}
+
+
+void QueryView::setActions(KToolBarPopupAction* NactBack, KToolBarPopupAction* NactForward, DictComboAction* NactQueryCombo)
+{
+ actBack = NactBack;
+ connect(actBack->popupMenu(),SIGNAL(activated(int)),SLOT(browseBack(int)));
+ actForward = NactForward;
+ connect(actForward->popupMenu(),SIGNAL(activated(int)),SLOT(browseForward(int)));
+ actQueryCombo = NactQueryCombo;
+}
+
+
+bool QueryView::browseBackPossible() const
+{
+ return (browsePos > 0)? true:false;
+}
+
+
+bool QueryView::browseForwardPossible() const
+{
+ return (browsePos+1 < browseList.count()) ? true:false;
+}
+
+
+void QueryView::optionsChanged()
+{
+ saveCurrentResultPos();
+
+ currentHTMLHeader = QString("<html><head><style type=\"text/css\">\n");
+ currentHTMLHeader += QString("body { background-color:%1; color:%2; }\n").arg(global->backgroundColor().name()).arg(global->textColor().name());
+ currentHTMLHeader += QString("a:link, a:active { color:%1; text-decoration:none; }\n").arg(global->linksColor().name());
+ currentHTMLHeader += QString("a:visited { color:%1; text-decoration:none; }\n").arg(global->visitedLinksColor().name());
+ currentHTMLHeader += QString("a:hover { color:%1; text-decoration:underline; }\n").arg(global->linksColor().name());
+ currentHTMLHeader += QString("p.heading { margin-left:0mm; margin-top:2mm; margin-bottom:2mm; padding:1mm; background-color:%1; color:%2; font-family:%3; font-size:%4pt; ").arg(global->headingsBackgroundColor().name()).arg(global->headingsTextColor().name()).arg(global->headingsFont().family()).arg(global->headingsFont().pointSize());
+ if (global->headingsFont().italic())
+ currentHTMLHeader += QString("font-style:italic; ");
+ if (global->headingsFont().bold())
+ currentHTMLHeader += QString("font-weight:bold; ");
+ currentHTMLHeader += QString("}\n");
+ currentHTMLHeader += QString("p.definition { margin-left:1.5mm; margin-top:2mm; margin-bottom:2mm;}\n");
+ currentHTMLHeader += QString("table { margin-left:1.5mm; margin-top:2mm; margin-bottom:2mm;}\n");
+ currentHTMLHeader += QString("pre { font-family:%1; font-size:%2pt; ").arg(global->textFont().family()).arg(global->textFont().pointSize());
+ if (global->textFont().italic())
+ currentHTMLHeader += QString("font-style:italic; ");
+ if (global->textFont().bold())
+ currentHTMLHeader += QString("font-weight:bold; ");
+ currentHTMLHeader += QString("}\n");
+ currentHTMLHeader += QString("</style></head>\n");
+
+ showResult(); // apply changes directly
+}
+
+
+void QueryView::stop()
+{
+ if (isRendering == true) {
+ part->closeURL();
+ isRendering = false;
+ emit(renderingStopped());
+ }
+}
+
+
+// print current result
+void QueryView::printQuery()
+{
+ part->view()->print();
+}
+
+
+// save the current result in an .html file
+void QueryView::saveQuery()
+{
+ if (!browseList.isEmpty()) {
+ BrowseData* brw = browseList.at(browsePos);
+ QString fName = brw->queryText+".html";
+ fName.replace(QRegExp("[\\s/]"),"_");
+ SaveHelper helper(fName,"*.html",global->topLevel);
+ QFile *file = helper.getFile(QString::null);
+
+ if (file) {
+ QTextStream stream(file);
+ stream.setEncoding(QTextStream::Locale);
+ stream << currentHTMLHeader+brw->html;
+ }
+ }
+}
+
+
+void QueryView::browseBack()
+{
+ if (browseBackPossible()) {
+ saveCurrentResultPos();
+ browsePos--;
+ actQueryCombo->setEditText(browseList.at(browsePos)->queryText);
+ showResult();
+ updateBrowseActions();
+ }
+}
+
+
+void QueryView::browseForward()
+{
+ if (browseForwardPossible()) {
+ saveCurrentResultPos();
+ browsePos++;
+ actQueryCombo->setEditText(browseList.at(browsePos)->queryText);
+ showResult();
+ updateBrowseActions();
+ }
+}
+
+
+void QueryView::selectAll()
+{
+ part->selectAll();
+}
+
+
+void QueryView::copySelection()
+{
+ kapp->clipboard()->setText(part->selectedText());
+}
+
+
+void QueryView::showFindDialog()
+{
+ KAction *act = part->actionCollection()->action("find");
+ if (act)
+ act->activate();
+}
+
+
+void QueryView::paletteChange ( const QPalette & )
+{
+
+ optionsChanged();
+}
+
+
+void QueryView::fontChange ( const QFont & )
+{
+ optionsChanged();
+}
+
+
+void QueryView::saveCurrentResultPos()
+{
+ if (!browseList.isEmpty()) {
+ browseList.at(browsePos)->xPos = part->view()->contentsX();
+ browseList.at(browsePos)->yPos = part->view()->contentsY();
+ }
+}
+
+
+void QueryView::showResult()
+{
+ if (!isRendering) {
+ isRendering = true;
+ emit(renderingStarted());
+ }
+
+ part->begin();
+ if (browseList.isEmpty()) {
+ part->write(currentHTMLHeader+"<body></body></html>");
+ part->end();
+ } else {
+ BrowseData* brw = browseList.at(browsePos);
+ emit(newCaption(getShortString(brw->queryText.simplifyWhiteSpace(),70)));
+ part->write(currentHTMLHeader+brw->html);
+ part->end();
+ part->view()->setFocus();
+ }
+}
+
+
+void QueryView::resultReady(const QString &result, const QString &query)
+{
+ BrowseData* brw = new BrowseData(result,query);
+
+ if (browseList.isEmpty()) {
+ browsePos = 0;
+ browseList.append(brw);
+ } else {
+ saveCurrentResultPos();
+ while (browseList.count()>browsePos+1)
+ browseList.removeLast();
+ browseList.append(brw);
+ browsePos++;
+ while (browseList.count()>global->maxBrowseListEntrys) {
+ browseList.removeFirst();
+ browsePos--;
+ }
+ }
+
+ showResult();
+ emit(enablePrintSave());
+ actQueryCombo->selectAll();
+ updateBrowseActions();
+}
+
+
+void QueryView::partCompleted()
+{
+ if (!browseList.isEmpty())
+ part->view()->setContentsPos(browseList.at(browsePos)->xPos,browseList.at(browsePos)->yPos);
+ if (isRendering) {
+ emit(renderingStopped());
+ isRendering = false;
+ }
+}
+
+
+void QueryView::slotURLRequest (const KURL &url, const KParts::URLArgs &)
+{
+ QString type = url.host();
+ QString urlText = url.prettyURL();
+ urlText.remove(0,8+type.length());
+
+ if (type.length()) { // valid url
+ if(type=="define")
+ emit(defineRequested(urlText));
+ if(type=="dbinfo")
+ interface->showDbInfo(urlText.utf8());
+ if(type=="realhttp")
+ kapp->invokeBrowser("http://"+urlText);
+ if(type=="realftp")
+ kapp->invokeBrowser("ftp://"+urlText);
+ }
+}
+
+
+void QueryView::middleButtonClicked()
+{
+ emit(clipboardRequested());
+}
+
+
+// construct the right-mouse-button-popup-menu on demand
+void QueryView::buildPopupMenu(const QString &url, const QPoint &point)
+{
+ rightBtnMenu->clear();
+
+ if (!url.isEmpty()) { // menuitem if mouse is over link
+ KURL u(url);
+ QString type = u.host();
+ popupLink = u.prettyURL();
+ popupLink.remove(0,8+type.length());
+
+ if (type.length()) { // valid url
+ if(type=="define") {
+ rightBtnMenu->insertItem(i18n("Define &Synonym"),
+ this,SLOT(popupDefineLink()));
+ rightBtnMenu->insertItem(i18n("M&atch Synonym"),
+ this,SLOT(popupMatchLink()));
+ rightBtnMenu->insertSeparator();
+ }
+ if(type=="dbinfo") {
+ rightBtnMenu->insertItem(i18n("D&atabase Information"),this,SLOT(popupDbInfo()));
+ rightBtnMenu->insertSeparator();
+ }
+ if(type=="realhttp") {
+ popupLink.prepend("http://");
+ rightBtnMenu->insertItem(SmallIcon("fileopen"),
+ i18n("&Open Link"),
+ this,SLOT(popupOpenLink()));
+ rightBtnMenu->insertSeparator();
+ }
+ if(type=="realftp") {
+ popupLink.prepend("ftp://");
+ rightBtnMenu->insertItem(SmallIcon("fileopen"),
+ i18n("&Open Link"),
+ this,SLOT(popupOpenLink()));
+ rightBtnMenu->insertSeparator();
+ }
+ }
+ }
+
+ if (part->hasSelection()) {
+ popupSelect = part->selectedText();
+ rightBtnMenu->insertItem(i18n("&Define Selection"),
+ this,SLOT(popupDefineSelect()));
+ rightBtnMenu->insertItem(i18n("&Match Selection"),
+ this,SLOT(popupMatchSelect()));
+ rightBtnMenu->insertSeparator();
+ } else {
+ kapp->clipboard()->setSelectionMode(false);
+ QString text = kapp->clipboard()->text();
+ if (text.isEmpty()) {
+ kapp->clipboard()->setSelectionMode(true);
+ text = kapp->clipboard()->text();
+ }
+ if (!text.isEmpty()) {
+ popupSelect = QApplication::clipboard()->text();
+ rightBtnMenu->insertItem(SmallIcon("define_clip"),
+ i18n("&Define Clipboard Content"),
+ this,SLOT(popupDefineSelect()));
+ rightBtnMenu->insertItem(i18n("&Match Clipboard Content"),
+ this,SLOT(popupMatchSelect()));
+ rightBtnMenu->insertSeparator();
+ }
+ }
+
+ int ID;
+
+ if (browseBackPossible()) { // if possible, show string
+ if (browseList.at(browsePos-1)->queryText.isEmpty())
+ rightBtnMenu->insertItem(SmallIcon("back"),
+ i18n("&Back: Information"),
+ this,SLOT(browseBack()));
+ else
+ rightBtnMenu->insertItem(SmallIcon("back"),
+ i18n("&Back: '%1'").arg(getShortString(browseList.at(browsePos-1)->queryText,25)),
+ this,SLOT(browseBack()));
+ } else {
+ ID = rightBtnMenu->insertItem(SmallIcon("back"), i18n("&Back"), this, SLOT(browseBack()));
+ rightBtnMenu->setItemEnabled(ID,false);
+ }
+
+ if (browseForwardPossible()) { // if possible, show string
+ if (browseList.at(browsePos+1)->queryText.isEmpty())
+ rightBtnMenu->insertItem(SmallIcon("forward"),
+ i18n("&Forward: Information"),
+ this,SLOT(browseForward()));
+ else
+ rightBtnMenu->insertItem(SmallIcon("forward"),
+ i18n("&Forward: '%1'").arg(getShortString(browseList.at(browsePos+1)->queryText,25)),
+ this,SLOT(browseForward()));
+ } else {
+ ID = rightBtnMenu->insertItem(SmallIcon("forward"),i18n("&Forward"),this,SLOT(browseForward()));
+ rightBtnMenu->setItemEnabled(ID,false);
+ }
+
+ rightBtnMenu->popup(point);
+}
+
+
+void QueryView::popupDefineLink()
+{
+ emit(defineRequested(popupLink));
+}
+
+
+void QueryView::popupMatchLink()
+{
+ emit(matchRequested(popupLink));
+}
+
+
+void QueryView::popupOpenLink()
+{
+ kapp->invokeBrowser(popupLink);
+}
+
+
+void QueryView::popupDefineSelect()
+{
+ emit(defineRequested(popupSelect));
+}
+
+
+void QueryView::popupMatchSelect()
+{
+ emit(matchRequested(popupSelect));
+}
+
+
+void QueryView::popupDbInfo()
+{
+
+ interface->showDbInfo(popupLink.utf8());
+}
+
+
+void QueryView::enableAction(const char * name, bool enabled)
+{
+ if (!strcmp(name,"copy"))
+ emit(enableCopy(enabled));
+}
+
+
+void QueryView::browseBack(int index)
+{
+ int x = browsePos-index;
+ if (x>=0) {
+ saveCurrentResultPos();
+ browsePos = x;
+ actQueryCombo->setEditText(browseList.at(browsePos)->queryText);
+ showResult();
+ QTimer::singleShot(0, this, SLOT(updateBrowseActions())); // don't clear the menu in this slot
+ }
+}
+
+
+void QueryView::browseForward(int index)
+{
+ int x = browsePos+index;
+ if (x < (int)(browseList.count())) {
+ saveCurrentResultPos();
+ browsePos = x;
+ actQueryCombo->setEditText(browseList.at(browsePos)->queryText);
+ showResult();
+ QTimer::singleShot(0, this, SLOT(updateBrowseActions())); // don't clear the menu in this slot
+ }
+}
+
+
+void QueryView::updateBrowseActions()
+{
+ if (browseBackPossible()) {
+ actBack->setEnabled(true);
+ if (browseList.at(browsePos-1)->queryText.isEmpty())
+ actBack->setText(i18n("&Back: Information"));
+ else
+ actBack->setText(i18n("&Back: '%1'").arg(getShortString(browseList.at(browsePos-1)->queryText,25)));
+
+ actBack->popupMenu()->clear();
+ int i = browsePos-1;
+ int num = 1;
+ QString s;
+ while ((i>=0)&&(num<=10)) {
+ s = browseList.at(i)->queryText;
+ if (s.isEmpty()) s = i18n("Information");
+ actBack->popupMenu()->insertItem(s,num);
+ num++;
+ i--;
+ }
+ } else {
+ actBack->setEnabled(false);
+ actBack->setText(i18n("&Back"));
+ actBack->popupMenu()->clear();
+ }
+
+ if (browseForwardPossible()) {
+ actForward->setEnabled(true);
+ if (browseList.at(browsePos+1)->queryText.isEmpty())
+ actForward->setText(i18n("&Forward: Information"));
+ else
+ actForward->setText(i18n("&Forward: '%1'").arg(getShortString(browseList.at(browsePos+1)->queryText,25)));
+
+ actForward->popupMenu()->clear();
+ int i = browsePos+1;
+ int num = 1;
+ QString s;
+ while ((i<(int)(browseList.count()))&&(num<=10)) {
+ s = browseList.at(i)->queryText;
+ if (s.isEmpty()) s = i18n("Information");
+ actForward->popupMenu()->insertItem(s,num);
+ num++;
+ i++;
+ }
+ } else {
+ actForward->setEnabled(false);
+ actForward->setText(i18n("&Forward"));
+ actForward->popupMenu()->clear();
+ }
+}
+
+//--------------------------------
+
+#include "queryview.moc"