Qt 5.9 | Qt WebEngine | WebEngine Demo Browser Example | cookiejar.cpp Example File

Qt 5.9.9 Reference Documentation

# cookiejar.cpp Example File

webenginewidgets/demobrowser/cookiejar.cpp

      /****************************************************************************
      **
      ** Copyright (C) 2016 The Qt Company Ltd.
      ** Contact: https://www.qt.io/licensing/
      **
      ** This file is part of the examples of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** Commercial License Usage
      ** Licensees holding valid commercial Qt licenses may use this file in
      ** accordance with the commercial license agreement provided with the
      ** Software or, alternatively, in accordance with the terms contained in
      ** a written agreement between you and The Qt Company. For licensing terms
      ** and conditions see https://www.qt.io/terms-conditions. For further
      ** information use the contact form at https://www.qt.io/contact-us.
      **
      ** BSD License Usage
      ** Alternatively, you may use this file under the terms of the BSD license
      ** as follows:
      **
      ** "Redistribution and use in source and binary forms, with or without
      ** modification, are permitted provided that the following conditions are
      ** met:
      **   * Redistributions of source code must retain the above copyright
      **     notice, this list of conditions and the following disclaimer.
      **   * Redistributions in binary form must reproduce the above copyright
      **     notice, this list of conditions and the following disclaimer in
      **     the documentation and/or other materials provided with the
      **     distribution.
      **   * Neither the name of The Qt Company Ltd nor the names of its
      **     contributors may be used to endorse or promote products derived
      **     from this software without specific prior written permission.
      **
      **
      ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      **
      ** $QT_END_LICENSE$
      **
      ****************************************************************************/

      #include "cookiejar.h"

      #include "autosaver.h"

      #include <QtCore/QDateTime>
      #include <QtCore/QDir>
      #include <QtCore/QFile>
      #include <QtCore/QMetaEnum>
      #include <QtCore/QSettings>
      #include <QtCore/QUrl>

      #include <QtWidgets/QCompleter>
      #include <QtGui/QDesktopServices>
      #include <QtGui/QFont>
      #include <QtGui/QFontMetrics>
      #include <QtWidgets/QHeaderView>
      #include <QtGui/QKeyEvent>
      #include <QtCore/QSortFilterProxyModel>
      #include <QtNetwork/QNetworkCookie>

      #include <QWebEngineSettings>

      #include <QtCore/QDebug>

      static const unsigned int JAR_VERSION = 23;

      QDataStream &operator<<(QDataStream &stream, const QList<QNetworkCookie> &list)
      {
          stream << JAR_VERSION;
          stream << quint32(list.size());
          for (int i = 0; i < list.size(); ++i)
              stream << list.at(i).toRawForm();
          return stream;
      }

      QDataStream &operator>>(QDataStream &stream, QList<QNetworkCookie> &list)
      {
          list.clear();

          quint32 version;
          stream >> version;

          if (version != JAR_VERSION)
              return stream;

          quint32 count;
          stream >> count;
          for (quint32 i = 0; i < count; ++i)
          {
              QByteArray value;
              stream >> value;
              QList<QNetworkCookie> newCookies = QNetworkCookie::parseCookies(value);
              if (newCookies.count() == 0 && value.length() != 0) {
                  qWarning() << "CookieJar: Unable to parse saved cookie:" << value;
              }
              for (int j = 0; j < newCookies.count(); ++j)
                  list.append(newCookies.at(j));
              if (stream.atEnd())
                  break;
          }
          return stream;
      }

      CookieJar::CookieJar(QObject *parent)
          : QNetworkCookieJar(parent)
          , m_loaded(false)
          , m_saveTimer(new AutoSaver(this))
          , m_acceptCookies(AcceptOnlyFromSitesNavigatedTo)
      {
      }

      CookieJar::~CookieJar()
      {
          if (m_keepCookies == KeepUntilExit)
              clear();
          m_saveTimer->saveIfNeccessary();
      }

      void CookieJar::clear()
      {
          setAllCookies(QList<QNetworkCookie>());
          m_saveTimer->changeOccurred();
          emit cookiesChanged();
      }

      void CookieJar::load()
      {
          if (m_loaded)
              return;
          // load cookies and exceptions
          qRegisterMetaTypeStreamOperators<QList<QNetworkCookie> >("QList<QNetworkCookie>");
          QSettings cookieSettings(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1String("/cookies.ini"), QSettings::IniFormat);
          setAllCookies(qvariant_cast<QList<QNetworkCookie> >(cookieSettings.value(QLatin1String("cookies"))));
          cookieSettings.beginGroup(QLatin1String("Exceptions"));
          m_exceptions_block = cookieSettings.value(QLatin1String("block")).toStringList();
          m_exceptions_allow = cookieSettings.value(QLatin1String("allow")).toStringList();
          m_exceptions_allowForSession = cookieSettings.value(QLatin1String("allowForSession")).toStringList();
          qSort(m_exceptions_block.begin(), m_exceptions_block.end());
          qSort(m_exceptions_allow.begin(), m_exceptions_allow.end());
          qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end());

          loadSettings();
      }

      void CookieJar::loadSettings()
      {
          QSettings settings;
          settings.beginGroup(QLatin1String("cookies"));
          QByteArray value = settings.value(QLatin1String("acceptCookies"),
                              QLatin1String("AcceptOnlyFromSitesNavigatedTo")).toByteArray();
          QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy"));
          m_acceptCookies = acceptPolicyEnum.keyToValue(value) == -1 ?
                              AcceptOnlyFromSitesNavigatedTo :
                              static_cast<AcceptPolicy>(acceptPolicyEnum.keyToValue(value));

          value = settings.value(QLatin1String("keepCookiesUntil"), QLatin1String("KeepUntilExpire")).toByteArray();
          QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy"));
          m_keepCookies = keepPolicyEnum.keyToValue(value) == -1 ?
                              KeepUntilExpire :
                              static_cast<KeepPolicy>(keepPolicyEnum.keyToValue(value));

          if (m_keepCookies == KeepUntilExit)
              setAllCookies(QList<QNetworkCookie>());

          m_loaded = true;
          emit cookiesChanged();
      }

      void CookieJar::save()
      {
          if (!m_loaded)
              return;
          purgeOldCookies();
          QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
          if (directory.isEmpty())
              directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName();
          if (!QFile::exists(directory)) {
              QDir dir;
              dir.mkpath(directory);
          }
          QSettings cookieSettings(directory + QLatin1String("/cookies.ini"), QSettings::IniFormat);
          QList<QNetworkCookie> cookies = allCookies();
          for (int i = cookies.count() - 1; i >= 0; --i) {
              if (cookies.at(i).isSessionCookie())
                  cookies.removeAt(i);
          }
          cookieSettings.setValue(QLatin1String("cookies"), QVariant::fromValue<QList<QNetworkCookie> >(cookies));
          cookieSettings.beginGroup(QLatin1String("Exceptions"));
          cookieSettings.setValue(QLatin1String("block"), m_exceptions_block);
          cookieSettings.setValue(QLatin1String("allow"), m_exceptions_allow);
          cookieSettings.setValue(QLatin1String("allowForSession"), m_exceptions_allowForSession);

          // save cookie settings
          QSettings settings;
          settings.beginGroup(QLatin1String("cookies"));
          QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy"));
          settings.setValue(QLatin1String("acceptCookies"), QLatin1String(acceptPolicyEnum.valueToKey(m_acceptCookies)));

          QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy"));
          settings.setValue(QLatin1String("keepCookiesUntil"), QLatin1String(keepPolicyEnum.valueToKey(m_keepCookies)));
      }

      void CookieJar::purgeOldCookies()
      {
          QList<QNetworkCookie> cookies = allCookies();
          if (cookies.isEmpty())
              return;
          int oldCount = cookies.count();
          QDateTime now = QDateTime::currentDateTime();
          for (int i = cookies.count() - 1; i >= 0; --i) {
              if (!cookies.at(i).isSessionCookie() && cookies.at(i).expirationDate() < now)
                  cookies.removeAt(i);
          }
          if (oldCount == cookies.count())
              return;
          setAllCookies(cookies);
          emit cookiesChanged();
      }

      QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl &url) const
      {
          CookieJar *that = const_cast<CookieJar*>(this);
          if (!m_loaded)
              that->load();

          QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings();
          if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) {
              QList<QNetworkCookie> noCookies;
              return noCookies;
          }

          return QNetworkCookieJar::cookiesForUrl(url);
      }

      bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
      {
          if (!m_loaded)
              load();

          QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings();
          if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled))
              return false;

          QString host = url.host();
          bool eBlock = qBinaryFind(m_exceptions_block.begin(), m_exceptions_block.end(), host) != m_exceptions_block.end();
          bool eAllow = qBinaryFind(m_exceptions_allow.begin(), m_exceptions_allow.end(), host) != m_exceptions_allow.end();
          bool eAllowSession = qBinaryFind(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end(), host) != m_exceptions_allowForSession.end();

          bool addedCookies = false;
          // pass exceptions
          bool acceptInitially = (m_acceptCookies != AcceptNever);
          if ((acceptInitially && !eBlock)
              || (!acceptInitially && (eAllow || eAllowSession))) {
              // pass url domain == cookie domain
              QDateTime soon = QDateTime::currentDateTime();
              soon = soon.addDays(90);
              foreach (QNetworkCookie cookie, cookieList) {
                  QList<QNetworkCookie> lst;
                  if (m_keepCookies == KeepUntilTimeLimit
                      && !cookie.isSessionCookie()
                      && cookie.expirationDate() > soon) {
                          cookie.setExpirationDate(soon);
                  }
                  lst += cookie;
                  if (QNetworkCookieJar::setCookiesFromUrl(lst, url)) {
                      addedCookies = true;
                  } else {
                      // finally force it in if wanted
                      if (m_acceptCookies == AcceptAlways) {
                          QList<QNetworkCookie> cookies = allCookies();
                          cookies += cookie;
                          setAllCookies(cookies);
                          addedCookies = true;
                      }
      #if 0
                      else
                          qWarning() << "setCookiesFromUrl failed" << url << cookieList.value(0).toRawForm();
      #endif
                  }
              }
          }

          if (addedCookies) {
              m_saveTimer->changeOccurred();
              emit cookiesChanged();
          }
          return addedCookies;
      }

      CookieJar::AcceptPolicy CookieJar::acceptPolicy() const
      {
          if (!m_loaded)
              (const_cast<CookieJar*>(this))->load();
          return m_acceptCookies;
      }

      void CookieJar::setAcceptPolicy(AcceptPolicy policy)
      {
          if (!m_loaded)
              load();
          if (policy == m_acceptCookies)
              return;
          m_acceptCookies = policy;
          m_saveTimer->changeOccurred();
      }

      CookieJar::KeepPolicy CookieJar::keepPolicy() const
      {
          if (!m_loaded)
              (const_cast<CookieJar*>(this))->load();
          return m_keepCookies;
      }

      void CookieJar::setKeepPolicy(KeepPolicy policy)
      {
          if (!m_loaded)
              load();
          if (policy == m_keepCookies)
              return;
          m_keepCookies = policy;
          m_saveTimer->changeOccurred();
      }

      QStringList CookieJar::blockedCookies() const
      {
          if (!m_loaded)
              (const_cast<CookieJar*>(this))->load();
          return m_exceptions_block;
      }

      QStringList CookieJar::allowedCookies() const
      {
          if (!m_loaded)
              (const_cast<CookieJar*>(this))->load();
          return m_exceptions_allow;
      }

      QStringList CookieJar::allowForSessionCookies() const
      {
          if (!m_loaded)
              (const_cast<CookieJar*>(this))->load();
          return m_exceptions_allowForSession;
      }

      void CookieJar::setBlockedCookies(const QStringList &list)
      {
          if (!m_loaded)
              load();
          m_exceptions_block = list;
          qSort(m_exceptions_block.begin(), m_exceptions_block.end());
          m_saveTimer->changeOccurred();
      }

      void CookieJar::setAllowedCookies(const QStringList &list)
      {
          if (!m_loaded)
              load();
          m_exceptions_allow = list;
          qSort(m_exceptions_allow.begin(), m_exceptions_allow.end());
          m_saveTimer->changeOccurred();
      }

      void CookieJar::setAllowForSessionCookies(const QStringList &list)
      {
          if (!m_loaded)
              load();
          m_exceptions_allowForSession = list;
          qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end());
          m_saveTimer->changeOccurred();
      }

      CookieModel::CookieModel(CookieJar *cookieJar, QObject *parent)
          : QAbstractTableModel(parent)
          , m_cookieJar(cookieJar)
      {
          connect(m_cookieJar, SIGNAL(cookiesChanged()), this, SLOT(cookiesChanged()));
          m_cookieJar->load();
      }

      QVariant CookieModel::headerData(int section, Qt::Orientation orientation, int role) const
      {
          if (role == Qt::SizeHintRole) {
              QFont font;
              font.setPointSize(10);
              QFontMetrics fm(font);
              int height = fm.height() + fm.height()/3;
              int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString());
              return QSize(width, height);
          }

          if (orientation == Qt::Horizontal) {
              if (role != Qt::DisplayRole)
                  return QVariant();

              switch (section) {
                  case 0:
                      return tr("Website");
                  case 1:
                      return tr("Name");
                  case 2:
                      return tr("Path");
                  case 3:
                      return tr("Secure");
                  case 4:
                      return tr("Expires");
                  case 5:
                      return tr("Contents");
                  default:
                      return QVariant();
              }
          }
          return QAbstractTableModel::headerData(section, orientation, role);
      }

      QVariant CookieModel::data(const QModelIndex &index, int role) const
      {
          QList<QNetworkCookie> lst;
          if (m_cookieJar)
              lst = m_cookieJar->allCookies();
          if (index.row() < 0 || index.row() >= lst.size())
              return QVariant();

          switch (role) {
          case Qt::DisplayRole:
          case Qt::EditRole: {
              QNetworkCookie cookie = lst.at(index.row());
              switch (index.column()) {
                  case 0:
                      return cookie.domain();
                  case 1:
                      return cookie.name();
                  case 2:
                      return cookie.path();
                  case 3:
                      return cookie.isSecure();
                  case 4:
                      return cookie.expirationDate();
                  case 5:
                      return cookie.value();
              }
              }
          case Qt::FontRole:{
              QFont font;
              font.setPointSize(10);
              return font;
              }
          }

          return QVariant();
      }

      int CookieModel::columnCount(const QModelIndex &parent) const
      {
          return (parent.isValid()) ? 0 : 6;
      }

      int CookieModel::rowCount(const QModelIndex &parent) const
      {
          return (parent.isValid() || !m_cookieJar) ? 0 : m_cookieJar->allCookies().count();
      }

      bool CookieModel::removeRows(int row, int count, const QModelIndex &parent)
      {
          if (parent.isValid() || !m_cookieJar)
              return false;
          int lastRow = row + count - 1;
          beginRemoveRows(parent, row, lastRow);
          QList<QNetworkCookie> lst = m_cookieJar->allCookies();
          for (int i = lastRow; i >= row; --i) {
              lst.removeAt(i);
          }
          m_cookieJar->setAllCookies(lst);
          endRemoveRows();
          return true;
      }

      void CookieModel::cookiesChanged()
      {
          beginResetModel();
          endResetModel();
      }

      CookiesDialog::CookiesDialog(CookieJar *cookieJar, QWidget *parent) : QDialog(parent)
      {
          setupUi(this);
          setWindowFlags(Qt::Sheet);
          CookieModel *model = new CookieModel(cookieJar, this);
          m_proxyModel = new QSortFilterProxyModel(this);
          connect(search, SIGNAL(textChanged(QString)),
                  m_proxyModel, SLOT(setFilterFixedString(QString)));
          connect(removeButton, SIGNAL(clicked()), cookiesTable, SLOT(removeOne()));
          connect(removeAllButton, SIGNAL(clicked()), cookiesTable, SLOT(removeAll()));
          m_proxyModel->setSourceModel(model);
          cookiesTable->verticalHeader()->hide();
          cookiesTable->setSelectionBehavior(QAbstractItemView::SelectRows);
          cookiesTable->setModel(m_proxyModel);
          cookiesTable->setAlternatingRowColors(true);
          cookiesTable->setTextElideMode(Qt::ElideMiddle);
          cookiesTable->setShowGrid(false);
          cookiesTable->setSortingEnabled(true);
          QFont f = font();
          f.setPointSize(10);
          QFontMetrics fm(f);
          int height = fm.height() + fm.height()/3;
          cookiesTable->verticalHeader()->setDefaultSectionSize(height);
          cookiesTable->verticalHeader()->setMinimumSectionSize(-1);
          for (int i = 0; i < model->columnCount(); ++i){
              int header = cookiesTable->horizontalHeader()->sectionSizeHint(i);
              switch (i) {
              case 0:
                  header = fm.width(QLatin1String("averagehost.domain.com"));
                  break;
              case 1:
                  header = fm.width(QLatin1String("_session_id"));
                  break;
              case 4:
                  header = fm.width(QDateTime::currentDateTime().toString(Qt::LocalDate));
                  break;
              }
              int buffer = fm.width(QLatin1String("xx"));
              header += buffer;
              cookiesTable->horizontalHeader()->resizeSection(i, header);
          }
          cookiesTable->horizontalHeader()->setStretchLastSection(true);
      }

      CookieExceptionsModel::CookieExceptionsModel(CookieJar *cookiejar, QObject *parent)
          : QAbstractTableModel(parent)
          , m_cookieJar(cookiejar)
      {
          m_allowedCookies = m_cookieJar->allowedCookies();
          m_blockedCookies = m_cookieJar->blockedCookies();
          m_sessionCookies = m_cookieJar->allowForSessionCookies();
      }

      QVariant CookieExceptionsModel::headerData(int section, Qt::Orientation orientation, int role) const
      {
          if (role == Qt::SizeHintRole) {
              QFont font;
              font.setPointSize(10);
              QFontMetrics fm(font);
              int height = fm.height() + fm.height()/3;
              int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString());
              return QSize(width, height);
          }

          if (orientation == Qt::Horizontal
              && role == Qt::DisplayRole) {
              switch (section) {
                  case 0:
                      return tr("Website");
                  case 1:
                      return tr("Status");
              }
          }
          return QAbstractTableModel::headerData(section, orientation, role);
      }

      QVariant CookieExceptionsModel::data(const QModelIndex &index, int role) const
      {
          if (index.row() < 0 || index.row() >= rowCount())
              return QVariant();

          switch (role) {
          case Qt::DisplayRole:
          case Qt::EditRole: {
              int row = index.row();
              if (row < m_allowedCookies.count()) {
                  switch (index.column()) {
                      case 0:
                          return m_allowedCookies.at(row);
                      case 1:
                          return tr("Allow");
                  }
              }
              row = row - m_allowedCookies.count();
              if (row < m_blockedCookies.count()) {
                  switch (index.column()) {
                      case 0:
                          return m_blockedCookies.at(row);
                      case 1:
                          return tr("Block");
                  }
              }
              row = row - m_blockedCookies.count();
              if (row < m_sessionCookies.count()) {
                  switch (index.column()) {
                      case 0:
                          return m_sessionCookies.at(row);
                      case 1:
                          return tr("Allow For Session");
                  }
              }
              }
          case Qt::FontRole:{
              QFont font;
              font.setPointSize(10);
              return font;
              }
          }
          return QVariant();
      }

      int CookieExceptionsModel::columnCount(const QModelIndex &parent) const
      {
          return (parent.isValid()) ? 0 : 2;
      }

      int CookieExceptionsModel::rowCount(const QModelIndex &parent) const
      {
          return (parent.isValid() || !m_cookieJar) ? 0 : m_allowedCookies.count() + m_blockedCookies.count() + m_sessionCookies.count();
      }

      bool CookieExceptionsModel::removeRows(int row, int count, const QModelIndex &parent)
      {
          if (parent.isValid() || !m_cookieJar)
              return false;

          int lastRow = row + count - 1;
          beginRemoveRows(parent, row, lastRow);
          for (int i = lastRow; i >= row; --i) {
              if (i < m_allowedCookies.count()) {
                  m_allowedCookies.removeAt(row);
                  continue;
              }
              i = i - m_allowedCookies.count();
              if (i < m_blockedCookies.count()) {
                  m_blockedCookies.removeAt(row);
                  continue;
              }
              i = i - m_blockedCookies.count();
              if (i < m_sessionCookies.count()) {
                  m_sessionCookies.removeAt(row);
                  continue;
              }
          }
          m_cookieJar->setAllowedCookies(m_allowedCookies);
          m_cookieJar->setBlockedCookies(m_blockedCookies);
          m_cookieJar->setAllowForSessionCookies(m_sessionCookies);
          endRemoveRows();
          return true;
      }

      CookiesExceptionsDialog::CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent)
          : QDialog(parent)
          , m_cookieJar(cookieJar)
      {
          setupUi(this);
          setWindowFlags(Qt::Sheet);
          connect(removeButton, SIGNAL(clicked()), exceptionTable, SLOT(removeOne()));
          connect(removeAllButton, SIGNAL(clicked()), exceptionTable, SLOT(removeAll()));
          exceptionTable->verticalHeader()->hide();
          exceptionTable->setSelectionBehavior(QAbstractItemView::SelectRows);
          exceptionTable->setAlternatingRowColors(true);
          exceptionTable->setTextElideMode(Qt::ElideMiddle);
          exceptionTable->setShowGrid(false);
          exceptionTable->setSortingEnabled(true);
          m_exceptionsModel = new CookieExceptionsModel(cookieJar, this);
          m_proxyModel = new QSortFilterProxyModel(this);
          m_proxyModel->setSourceModel(m_exceptionsModel);
          connect(search, SIGNAL(textChanged(QString)),
                  m_proxyModel, SLOT(setFilterFixedString(QString)));
          exceptionTable->setModel(m_proxyModel);

          CookieModel *cookieModel = new CookieModel(cookieJar, this);
          domainLineEdit->setCompleter(new QCompleter(cookieModel, domainLineEdit));

          connect(domainLineEdit, SIGNAL(textChanged(QString)),
                  this, SLOT(textChanged(QString)));
          connect(blockButton, SIGNAL(clicked()), this, SLOT(block()));
          connect(allowButton, SIGNAL(clicked()), this, SLOT(allow()));
          connect(allowForSessionButton, SIGNAL(clicked()), this, SLOT(allowForSession()));

          QFont f = font();
          f.setPointSize(10);
          QFontMetrics fm(f);
          int height = fm.height() + fm.height()/3;
          exceptionTable->verticalHeader()->setDefaultSectionSize(height);
          exceptionTable->verticalHeader()->setMinimumSectionSize(-1);
          for (int i = 0; i < m_exceptionsModel->columnCount(); ++i){
              int header = exceptionTable->horizontalHeader()->sectionSizeHint(i);
              switch (i) {
              case 0:
                  header = fm.width(QLatin1String("averagebiglonghost.domain.com"));
                  break;
              case 1:
                  header = fm.width(QLatin1String("Allow For Session"));
                  break;
              }
              int buffer = fm.width(QLatin1String("xx"));
              header += buffer;
              exceptionTable->horizontalHeader()->resizeSection(i, header);
          }
      }

      void CookiesExceptionsDialog::textChanged(const QString &text)
      {
          bool enabled = !text.isEmpty();
          blockButton->setEnabled(enabled);
          allowButton->setEnabled(enabled);
          allowForSessionButton->setEnabled(enabled);
      }

      void CookiesExceptionsDialog::block()
      {
          if (domainLineEdit->text().isEmpty())
              return;
          m_exceptionsModel->m_blockedCookies.append(domainLineEdit->text());
          m_cookieJar->setBlockedCookies(m_exceptionsModel->m_blockedCookies);
          m_exceptionsModel->beginResetModel();
          m_exceptionsModel->endResetModel();
      }

      void CookiesExceptionsDialog::allow()
      {
          if (domainLineEdit->text().isEmpty())
              return;
          m_exceptionsModel->m_allowedCookies.append(domainLineEdit->text());
          m_cookieJar->setAllowedCookies(m_exceptionsModel->m_allowedCookies);
          m_exceptionsModel->beginResetModel();
          m_exceptionsModel->endResetModel();
      }

      void CookiesExceptionsDialog::allowForSession()
      {
          if (domainLineEdit->text().isEmpty())
              return;
          m_exceptionsModel->m_sessionCookies.append(domainLineEdit->text());
          m_cookieJar->setAllowForSessionCookies(m_exceptionsModel->m_sessionCookies);
          m_exceptionsModel->beginResetModel();
          m_exceptionsModel->endResetModel();
      }