/* ------------------------------------------------------------- queryview.cpp (part of The KDE Dictionary Client) Copyright (C) 2000-2001 Christian Gebauer 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 #include #include #include #include #include #include #include #include #include #include #include "actions.h" #include "options.h" #include "dict.h" #include "queryview.h" #include #include //******** SaveHelper ******************************************* TQString SaveHelper::lastPath; SaveHelper::SaveHelper(const TQString &saveName, const TQString &filter, TQWidget *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 (TDEIO::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; } } TQFile* SaveHelper::getFile(const TQString &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 (TQFileInfo(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 TQFile(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 TQString &Nhtml, const TQString &NqueryText) : html(Nhtml),queryText(NqueryText),xPos(0),yPos(0) {} //********* DictHTMLPart ****************************************** DictHTMLPart::DictHTMLPart(TQWidget *parentWidget, const char *widgetname) : TDEHTMLPart(parentWidget,widgetname) {} DictHTMLPart::~DictHTMLPart() {} void DictHTMLPart::tdehtmlMouseReleaseEvent(tdehtml::MouseReleaseEvent *event) { if (event->qmouseEvent()->button()==Qt::MidButton) emit(middleButtonClicked()); else TDEHTMLPart::tdehtmlMouseReleaseEvent(event); } //********* QueryView ****************************************** QueryView::QueryView(TQWidget *_parent) : TQVBox( _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(TQ_NoFocus); connect(part, TQT_SIGNAL(completed()), TQT_SLOT(partCompleted())); connect(part, TQT_SIGNAL(middleButtonClicked()), TQT_SLOT(middleButtonClicked())); rightBtnMenu = new TDEPopupMenu(this); connect(part,TQT_SIGNAL(popupMenu(const TQString &, const TQPoint &)),this,TQT_SLOT(buildPopupMenu(const TQString &, const TQPoint &))); connect(part->browserExtension(),TQT_SIGNAL(openURLRequest(const KURL &,const KParts::URLArgs &)), this,TQT_SLOT(slotURLRequest(const KURL &,const KParts::URLArgs &))); connect(part->browserExtension(),TQT_SIGNAL(enableAction(const char *,bool)),this,TQT_SLOT(enableAction(const char *,bool))); TQTimer::singleShot( 0, this, TQT_SLOT(optionsChanged()) ); connect(interface,TQT_SIGNAL(resultReady(const TQString &, const TQString &)), TQT_SLOT(resultReady(const TQString &, const TQString &))); } QueryView::~QueryView() {} void QueryView::setActions(TDEToolBarPopupAction* NactBack, TDEToolBarPopupAction* NactForward, DictComboAction* NactQueryCombo) { actBack = NactBack; connect(actBack->popupMenu(),TQT_SIGNAL(activated(int)),TQT_SLOT(browseBack(int))); actForward = NactForward; connect(actForward->popupMenu(),TQT_SIGNAL(activated(int)),TQT_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 = TQString("\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); TQString fName = brw->queryText+".html"; fName.replace(TQRegExp("[\\s/]"),"_"); SaveHelper helper(fName,"*.html",global->topLevel); TQFile *file = helper.getFile(TQString()); if (file) { TQTextStream stream(file); stream.setEncoding(TQTextStream::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() { TDEAction *act = part->actionCollection()->action("find"); if (act) act->activate(); } void QueryView::paletteChange ( const TQPalette & ) { optionsChanged(); } void QueryView::fontChange ( const TQFont & ) { 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+""); 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 TQString &result, const TQString &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 &) { TQString type = url.host(); TQString 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 TQString &url, const TQPoint &point) { rightBtnMenu->clear(); if (!url.isEmpty()) { // menuitem if mouse is over link KURL u(url); TQString 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,TQT_SLOT(popupDefineLink())); rightBtnMenu->insertItem(i18n("M&atch Synonym"), this,TQT_SLOT(popupMatchLink())); rightBtnMenu->insertSeparator(); } if(type=="dbinfo") { rightBtnMenu->insertItem(i18n("D&atabase Information"),this,TQT_SLOT(popupDbInfo())); rightBtnMenu->insertSeparator(); } if(type=="realhttp") { popupLink.prepend("http://"); rightBtnMenu->insertItem(SmallIcon("document-open"), i18n("&Open Link"), this,TQT_SLOT(popupOpenLink())); rightBtnMenu->insertSeparator(); } if(type=="realftp") { popupLink.prepend("ftp://"); rightBtnMenu->insertItem(SmallIcon("document-open"), i18n("&Open Link"), this,TQT_SLOT(popupOpenLink())); rightBtnMenu->insertSeparator(); } } } if (part->hasSelection()) { popupSelect = part->selectedText(); rightBtnMenu->insertItem(i18n("&Define Selection"), this,TQT_SLOT(popupDefineSelect())); rightBtnMenu->insertItem(i18n("&Match Selection"), this,TQT_SLOT(popupMatchSelect())); rightBtnMenu->insertSeparator(); } else { kapp->clipboard()->setSelectionMode(false); TQString text = kapp->clipboard()->text(); if (text.isEmpty()) { kapp->clipboard()->setSelectionMode(true); text = kapp->clipboard()->text(); } if (!text.isEmpty()) { popupSelect = TQApplication::clipboard()->text(); rightBtnMenu->insertItem(SmallIcon("define_clip"), i18n("&Define Clipboard Content"), this,TQT_SLOT(popupDefineSelect())); rightBtnMenu->insertItem(i18n("&Match Clipboard Content"), this,TQT_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,TQT_SLOT(browseBack())); else rightBtnMenu->insertItem(SmallIcon("back"), i18n("&Back: '%1'").arg(getShortString(browseList.at(browsePos-1)->queryText,25)), this,TQT_SLOT(browseBack())); } else { ID = rightBtnMenu->insertItem(SmallIcon("back"), i18n("&Back"), this, TQT_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,TQT_SLOT(browseForward())); else rightBtnMenu->insertItem(SmallIcon("forward"), i18n("&Forward: '%1'").arg(getShortString(browseList.at(browsePos+1)->queryText,25)), this,TQT_SLOT(browseForward())); } else { ID = rightBtnMenu->insertItem(SmallIcon("forward"),i18n("&Forward"),this,TQT_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(); TQTimer::singleShot(0, this, TQT_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(); TQTimer::singleShot(0, this, TQT_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; TQString 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; TQString 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"