/* KLayout Layout Viewer Copyright (C) 2006-2016 Matthias Koefferlein 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "layBrowserPanel.h" #include "tlExceptions.h" #include "tlInternational.h" #include "tlException.h" #include "ui_BrowserPanel.h" #include #if QT_VERSION >= 0x050000 # include #endif namespace lay { // ------------------------------------------------------------- QVariant BrowserTextWidget::loadResource (int type, const QUrl &url) { if (mp_panel && url.scheme () == QString::fromUtf8 ("int")) { return mp_panel->loadResource (type, url); } else { return QTextBrowser::loadResource (type, url); } } // ------------------------------------------------------------- BrowserPanel::BrowserPanel (QWidget *parent) : QWidget (parent), m_back_dm (this, &BrowserPanel::back) { init (); } void BrowserPanel::init () { m_enable_load = false; m_enable_reject = false; mp_source.reset (0); mp_ui = new Ui::BrowserPanel (); mp_ui->setupUi (this); mp_ui->browser->setReadOnly (true); mp_ui->browser->set_panel (this); mp_ui->browser->setWordWrapMode (QTextOption::WordWrap); connect (mp_ui->back_pb, SIGNAL (clicked ()), this, SLOT (back ())); connect (mp_ui->forward_pb, SIGNAL (clicked ()), this, SLOT (forward ())); connect (mp_ui->next_topic_pb, SIGNAL (clicked ()), this, SLOT (next ())); connect (mp_ui->prev_topic_pb, SIGNAL (clicked ()), this, SLOT (prev ())); connect (mp_ui->home_pb, SIGNAL (clicked ()), this, SLOT (home ())); connect (mp_ui->searchEdit, SIGNAL (returnPressed ()), this, SLOT (search_edited ())); connect (mp_ui->browser, SIGNAL (textChanged ()), this, SLOT (text_changed ())); connect (mp_ui->browser, SIGNAL (backwardAvailable (bool)), mp_ui->back_pb, SLOT (setEnabled (bool))); connect (mp_ui->browser, SIGNAL (forwardAvailable (bool)), mp_ui->forward_pb, SLOT (setEnabled (bool))); mp_ui->searchEdit->hide (); set_label (std::string ()); } BrowserPanel::~BrowserPanel () { set_source (0); mp_ui->browser->set_panel (0); delete mp_ui; mp_ui = 0; } std::string BrowserPanel::title () const { return tl::to_string (m_current_title); } std::string BrowserPanel::url () const { return m_cached_url; } void BrowserPanel::text_changed () { QString title = mp_ui->browser->document ()->metaInformation (QTextDocument::DocumentTitle); if (title != m_current_title) { m_current_title = title; emit title_changed (title); } } void BrowserPanel::load (const std::string &s) { mp_ui->browser->setSource (QUrl (tl::to_qstring (s))); } void BrowserPanel::set_source (BrowserSource *source) { m_enable_reject = false; m_enable_load = false; if (mp_source.get ()) { mp_source->detach (this); // release the reference to the source object mp_source->gsi::ObjectBase::release (); } mp_source.reset (source); if (mp_source.get ()) { m_enable_load = true; // hold a reference to the source object for GSI mp_source->gsi::ObjectBase::keep (); mp_source->attach (this); mp_ui->browser->clearHistory (); reload (); m_enable_reject = true; } } void BrowserPanel::set_home (const std::string &url) { m_home = url; home (); } void BrowserPanel::reload () { // clear caches to force a reload m_cached_url = ""; m_cached_text = ""; // disable reload while we are in a loadResource call - clearing the cache will be sufficient if (m_enable_load) { mp_ui->browser->reload (); emit url_changed (tl::to_qstring (m_cached_url)); } } void BrowserPanel::prev () { mp_ui->browser->setSource (QUrl (tl::to_qstring (m_cached_prev_url))); reload (); } void BrowserPanel::next () { mp_ui->browser->setSource (QUrl (tl::to_qstring (m_cached_next_url))); reload (); } void BrowserPanel::back () { mp_ui->browser->backward (); } void BrowserPanel::forward () { mp_ui->browser->forward (); } void BrowserPanel::home () { bool needs_reload = (m_home == m_cached_url); mp_ui->browser->setSource (QUrl (tl::to_qstring (m_home))); if (needs_reload) { reload (); } } QSize BrowserPanel::sizeHint () const { return QSize (600, 400); } void BrowserPanel::search (const std::string &s) { if (! s.empty ()) { QUrl url (tl::to_qstring (m_search_url)); #if QT_VERSION >= 0x050000 QUrlQuery qi; qi.addQueryItem (tl::to_qstring (m_search_query_item), tl::to_qstring (s)); url.setQuery (qi); #else QList > qi; qi.push_back (QPair (tl::to_qstring (m_search_query_item), tl::to_qstring (s))); url.setQueryItems (qi); #endif load (url.toEncoded ().constData ()); } } void BrowserPanel::search_edited () { if (mp_ui->searchEdit->text ().size () > 0) { QUrl url (tl::to_qstring (m_search_url)); #if QT_VERSION >= 0x050000 QUrlQuery qi; qi.addQueryItem (tl::to_qstring (m_search_query_item), mp_ui->searchEdit->text ()); url.setQuery (qi); #else QList > qi; qi.push_back (QPair (tl::to_qstring (m_search_query_item), mp_ui->searchEdit->text ())); url.setQueryItems (qi); #endif load (url.toEncoded ().constData ()); } } void BrowserPanel::set_search_url (const std::string &url, const std::string &query_item) { m_search_url = url; m_search_query_item = query_item; mp_ui->searchEdit->setVisible (! url.empty ()); } void BrowserPanel::set_label (const std::string &text) { mp_ui->label->setText (tl::to_qstring (text)); mp_ui->label->setVisible (! text.empty ()); } QVariant BrowserPanel::loadResource (int type, const QUrl &url) { if (type == QTextDocument::ImageResource) { BEGIN_PROTECTED return QVariant (mp_source->get_image (tl::to_string (url.toString ()))); END_PROTECTED return QVariant (); } else if (type == QTextDocument::StyleSheetResource) { BEGIN_PROTECTED return QVariant (tl::to_qstring (mp_source->get_css (tl::to_string (url.toString ())))); END_PROTECTED return QVariant (); } else if (type != QTextDocument::HtmlResource) { return QVariant (); } else { QVariant ret; // recursion sentinel: avoid recursion by any action within mp_source->get that causes a "loadResource" if (! m_enable_load || !mp_source.get ()) { // return any dummy in this case - otherwise the QTestBrowser complains about not having anything. return QVariant (QString::fromUtf8 (" ")); } m_enable_load = false; // Qt sets the override cursor in response to link clicks - this is not appropriate for some // GSI callback implementations that show InputDialogs for example. Therefore we install out own // (normal) override cursor. QApplication::setOverrideCursor (QCursor (Qt::ArrowCursor)); BEGIN_PROTECTED std::string u = tl::to_string (url.toString ()); std::string s; std::string nu, pu; if (u == m_cached_url) { s = m_cached_text; nu = m_cached_next_url; pu = m_cached_prev_url; } else { s = mp_source->get (u); nu = mp_source->next_topic (u); pu = mp_source->prev_topic (u); } if (s.empty ()) { s = " "; // QTextBrowser needs at least something // The only way (as far as I know in Qt <4.2) to suppress navigation to // the Url is to schedule a delayed "back" signal. In Qt >= 4.2 we could register // an external handler for "int" schemes that would do nothing .. if (m_enable_reject) { m_back_dm (); } } else { // to avoid regeneration of text on artificial "back" events, the last page is cached m_cached_text = s; m_cached_url = u; m_cached_next_url = nu; m_cached_prev_url = pu; } ret = QVariant (tl::to_qstring (s)); if (pu.empty () && nu.empty ()) { mp_ui->prev_topic_pb->hide (); mp_ui->next_topic_pb->hide (); } else { mp_ui->prev_topic_pb->show (); mp_ui->prev_topic_pb->setEnabled (! pu.empty ()); mp_ui->next_topic_pb->show (); mp_ui->next_topic_pb->setEnabled (! nu.empty ()); } END_PROTECTED QApplication::restoreOverrideCursor (); m_enable_load = true; return ret; } } // ------------------------------------------------------------- BrowserSource::BrowserSource () { // .. nothing yet .. } BrowserSource::BrowserSource (const std::string &html) : m_default_html (html) { // .. nothing yet .. } BrowserSource::~BrowserSource () { std::set owners; owners.swap (mp_owners); for (std::set::const_iterator o = owners.begin (); o != owners.end (); ++o) { (*o)->set_source (0); } } std::string BrowserSource::get_css (const std::string & /*url*/) { return std::string (); } QImage BrowserSource::get_image (const std::string & /*url*/) { return QImage (); } std::string BrowserSource::get (const std::string & /*url*/) { return m_default_html; } void BrowserSource::detach (lay::BrowserPanel *d) { mp_owners.erase (d); } void BrowserSource::attach (lay::BrowserPanel *d) { mp_owners.insert (d); } }