mirror of https://github.com/KLayout/klayout.git
414 lines
9.6 KiB
C++
414 lines
9.6 KiB
C++
|
|
/*
|
|
|
|
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 <cstdio>
|
|
#if QT_VERSION >= 0x050000
|
|
# include <QUrlQuery>
|
|
#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<QPair<QString, QString> > qi;
|
|
qi.push_back (QPair<QString, QString> (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<QPair<QString, QString> > qi;
|
|
qi.push_back (QPair<QString, QString> (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<BrowserPanel *> owners;
|
|
owners.swap (mp_owners);
|
|
for (std::set<BrowserPanel *>::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);
|
|
}
|
|
|
|
}
|
|
|
|
|