<commit_before>/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

   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 Mumble Developers 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 FOUNDATION 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.
*/

#include "murmur_pch.h"

#include "SSL.h"

#include "Version.h"

QString MumbleSSL::defaultOpenSSLCipherString() {
	return QLatin1String("EECDH+AESGCM:AES256-SHA:AES128-SHA");
}

QList<QSslCipher> MumbleSSL::ciphersFromOpenSSLCipherString(QString cipherString) {
	QList<QSslCipher> chosenCiphers;

	SSL_CTX *ctx = NULL;
	SSL *ssl = NULL;
	const SSL_METHOD *meth = NULL;
	int i = 0;

	QByteArray csbuf = cipherString.toLatin1();
	const char *ciphers = csbuf.constData();

	meth = SSLv23_server_method();
	if (meth == NULL) {
		qWarning("MumbleSSL: unable to get SSL method");
		goto out;
	}

	ctx = SSL_CTX_new(meth);
	if (ctx == NULL) {
		qWarning("MumbleSSL: unable to allocate SSL_CTX");
		goto out;
	}

	if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
		qWarning("MumbleSSL: error parsing OpenSSL cipher string in ciphersFromOpenSSLCipherString");
		goto out;
	}

	ssl = SSL_new(ctx);
	if (ssl == NULL) {
		qWarning("MumbleSSL: unable to create SSL object in ciphersFromOpenSSLCipherString");
		goto out;
	}

	while (1) {
		const char *name = SSL_get_cipher_list(ssl, i);
		if (name == NULL) {
			break;
		}
		QSslCipher c = QSslCipher(QString::fromLatin1(name));
		if (!c.isNull()) {
			chosenCiphers << c;
		}
		++i;
	}

out:
	SSL_CTX_free(ctx);
	SSL_free(ssl);
	return chosenCiphers;
}

void MumbleSSL::addSystemCA() {
#if QT_VERSION < 0x040700 && !defined(NO_SYSTEM_CA_OVERRIDE)
#if defined(Q_OS_WIN)
	QStringList qsl;
	qsl << QLatin1String("Ca");
	qsl << QLatin1String("Root");
	qsl << QLatin1String("AuthRoot");
	foreach(const QString &store, qsl) {
		HCERTSTORE hCertStore;
		PCCERT_CONTEXT pCertContext = NULL;

		bool found = false;

		hCertStore = CertOpenSystemStore(NULL, store.utf16());
		if (! hCertStore) {
			qWarning("SSL: Failed to open CA store %s", qPrintable(store));
			continue;
		}

		while (pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)) {
			QByteArray qba(reinterpret_cast<const char *>(pCertContext->pbCertEncoded), pCertContext->cbCertEncoded);

			QList<QSslCertificate> ql = QSslCertificate::fromData(qba, QSsl::Pem);
			ql += QSslCertificate::fromData(qba, QSsl::Der);
			if (! ql.isEmpty()) {
				found = true;
				QSslSocket::addDefaultCaCertificates(ql);
			}
		}
		if (found)
			qWarning("SSL: Added CA certificates from system store '%s'", qPrintable(store));

		CertCloseStore(hCertStore, 0);
	}

#elif defined(Q_OS_MAC)
	CFArrayRef certs = NULL;
	bool found = false;

	if (SecTrustCopyAnchorCertificates(&certs) == noErr) {
		int ncerts = CFArrayGetCount(certs);
		for (int i = 0; i < ncerts; i++) {
			CFDataRef data = NULL;

			SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(const_cast<void *>(CFArrayGetValueAtIndex(certs, i)));
			if (! cert)
				continue;

			if (SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data) == noErr) {
				const char *ptr = reinterpret_cast<const char *>(CFDataGetBytePtr(data));
				int len = CFDataGetLength(data);
				QByteArray qba(ptr, len);

				QList<QSslCertificate> ql = QSslCertificate::fromData(qba, QSsl::Pem);
				if (! ql.isEmpty()) {
					found = true;
					QSslSocket::addDefaultCaCertificates(ql);
				}
			}
		}

		CFRelease(certs);

		if (found)
			qWarning("SSL: Added CA certificates from 'System Roots' store.");
	}
#elif defined(Q_OS_UNIX)
	QStringList qsl;

#ifdef SYSTEM_CA_DIR
	QSslSocket::addDefaultCaCertificates(QLatin1String(MUMTEXT(SYSTEM_CA_DIR)));
#else
#ifdef SYSTEM_CA_BUNDLE
	qsl << QLatin1String(MUMTEXT(SYSTEM_CA_BUNDLE));
#else
#ifdef __FreeBSD__
	qsl << QLatin1String("/usr/local/share/certs/ca-root-nss.crt");
#else
	qsl << QLatin1String("/etc/pki/tls/certs/ca-bundle.crt");
	qsl << QLatin1String("/etc/ssl/certs/ca-certificates.crt");
#endif
#endif

	foreach(const QString &filename, qsl) {
		QFile f(filename);
		if (f.exists() && f.open(QIODevice::ReadOnly)) {
			QList<QSslCertificate> ql = QSslCertificate::fromDevice(&f, QSsl::Pem);
			ql += QSslCertificate::fromDevice(&f, QSsl::Der);
			if (! ql.isEmpty()) {
				qWarning("SSL: Added CA certificates from '%s'", qPrintable(filename));
				QSslSocket::addDefaultCaCertificates(ql);
			}
		}
	}
#endif // SYSTEM_CA_DIR
#endif // Q_OS_UNIX

	QSet<QByteArray> digests;
	QList<QSslCertificate> ql;
	foreach(const QSslCertificate &crt, QSslSocket::defaultCaCertificates()) {
		QByteArray digest = crt.digest(QCryptographicHash::Sha1);
		if (! digests.contains(digest) && crt.isValid()) {
			ql << crt;
			digests.insert(digest);
		}
	}
	QSslSocket::setDefaultCaCertificates(ql);
#endif // NO_SYSTEM_CA_OVERRIDE

#if QT_VERSION >= 0x040800
	// Don't perform on-demand loading of root certificates
	QSslSocket::addDefaultCaCertificates(QSslSocket::systemCaCertificates());
#endif

#ifdef Q_OS_WIN
	// Work around issue #1271.
	// Skype's click-to-call feature creates an enormous
	// amount of certificates in the Root CA store.
	{
		QSslConfiguration sslCfg = QSslConfiguration::defaultConfiguration();
		QList<QSslCertificate> caList = sslCfg.caCertificates();

		QList<QSslCertificate> filteredCaList;
		foreach (QSslCertificate cert, caList) {
#if QT_VERSION >= 0x050000
			QStringList orgs = cert.subjectInfo(QSslCertificate::Organization);
			bool skip = false;
			foreach (QString ou, orgs) {
				if (ou.contains(QLatin1String("Skype"), Qt::CaseInsensitive)) {
					skip = true;
					break;
				}
			}
			if (skip) {
				continue;
			}
#else
			QString ou = cert.subjectInfo(QSslCertificate::Organization);
			if (ou.contains(QLatin1String("Skype"), Qt::CaseInsensitive)) {
				continue;
			}
#endif
			filteredCaList.append(cert);
		}

		sslCfg.setCaCertificates(filteredCaList);
		QSslConfiguration::setDefaultConfiguration(sslCfg);

		qWarning("SSL: CA certificate filter applied. Filtered size: %i, original size: %i", filteredCaList.size(), caList.size());
	}
#endif
}
<commit_msg>SSL: fix build for Qt 4.<commit_after>/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

   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 Mumble Developers 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 FOUNDATION 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.
*/

#include "murmur_pch.h"

#include "SSL.h"

#include "Version.h"

QString MumbleSSL::defaultOpenSSLCipherString() {
	return QLatin1String("EECDH+AESGCM:AES256-SHA:AES128-SHA");
}

QList<QSslCipher> MumbleSSL::ciphersFromOpenSSLCipherString(QString cipherString) {
	QList<QSslCipher> chosenCiphers;

	SSL_CTX *ctx = NULL;
	SSL *ssl = NULL;
	const SSL_METHOD *meth = NULL;
	int i = 0;

	QByteArray csbuf = cipherString.toLatin1();
	const char *ciphers = csbuf.constData();

	meth = SSLv23_server_method();
	if (meth == NULL) {
		qWarning("MumbleSSL: unable to get SSL method");
		goto out;
	}

	ctx = SSL_CTX_new(meth);
	if (ctx == NULL) {
		qWarning("MumbleSSL: unable to allocate SSL_CTX");
		goto out;
	}

	if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
		qWarning("MumbleSSL: error parsing OpenSSL cipher string in ciphersFromOpenSSLCipherString");
		goto out;
	}

	ssl = SSL_new(ctx);
	if (ssl == NULL) {
		qWarning("MumbleSSL: unable to create SSL object in ciphersFromOpenSSLCipherString");
		goto out;
	}

	while (1) {
		const char *name = SSL_get_cipher_list(ssl, i);
		if (name == NULL) {
			break;
		}
#if QT_VERSION >= 0x050000
		QSslCipher c = QSslCipher(QString::fromLatin1(name));
		if (!c.isNull()) {
			chosenCiphers << c;
		}
#else
		foreach (const QSslCipher &c, QSslSocket::supportedCiphers()) {
			if (c.name() == QString::fromLatin1(name)) {
				chosenCiphers << c;
			}
		}
#endif
		++i;
	}

out:
	SSL_CTX_free(ctx);
	SSL_free(ssl);
	return chosenCiphers;
}

void MumbleSSL::addSystemCA() {
#if QT_VERSION < 0x040700 && !defined(NO_SYSTEM_CA_OVERRIDE)
#if defined(Q_OS_WIN)
	QStringList qsl;
	qsl << QLatin1String("Ca");
	qsl << QLatin1String("Root");
	qsl << QLatin1String("AuthRoot");
	foreach(const QString &store, qsl) {
		HCERTSTORE hCertStore;
		PCCERT_CONTEXT pCertContext = NULL;

		bool found = false;

		hCertStore = CertOpenSystemStore(NULL, store.utf16());
		if (! hCertStore) {
			qWarning("SSL: Failed to open CA store %s", qPrintable(store));
			continue;
		}

		while (pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)) {
			QByteArray qba(reinterpret_cast<const char *>(pCertContext->pbCertEncoded), pCertContext->cbCertEncoded);

			QList<QSslCertificate> ql = QSslCertificate::fromData(qba, QSsl::Pem);
			ql += QSslCertificate::fromData(qba, QSsl::Der);
			if (! ql.isEmpty()) {
				found = true;
				QSslSocket::addDefaultCaCertificates(ql);
			}
		}
		if (found)
			qWarning("SSL: Added CA certificates from system store '%s'", qPrintable(store));

		CertCloseStore(hCertStore, 0);
	}

#elif defined(Q_OS_MAC)
	CFArrayRef certs = NULL;
	bool found = false;

	if (SecTrustCopyAnchorCertificates(&certs) == noErr) {
		int ncerts = CFArrayGetCount(certs);
		for (int i = 0; i < ncerts; i++) {
			CFDataRef data = NULL;

			SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(const_cast<void *>(CFArrayGetValueAtIndex(certs, i)));
			if (! cert)
				continue;

			if (SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data) == noErr) {
				const char *ptr = reinterpret_cast<const char *>(CFDataGetBytePtr(data));
				int len = CFDataGetLength(data);
				QByteArray qba(ptr, len);

				QList<QSslCertificate> ql = QSslCertificate::fromData(qba, QSsl::Pem);
				if (! ql.isEmpty()) {
					found = true;
					QSslSocket::addDefaultCaCertificates(ql);
				}
			}
		}

		CFRelease(certs);

		if (found)
			qWarning("SSL: Added CA certificates from 'System Roots' store.");
	}
#elif defined(Q_OS_UNIX)
	QStringList qsl;

#ifdef SYSTEM_CA_DIR
	QSslSocket::addDefaultCaCertificates(QLatin1String(MUMTEXT(SYSTEM_CA_DIR)));
#else
#ifdef SYSTEM_CA_BUNDLE
	qsl << QLatin1String(MUMTEXT(SYSTEM_CA_BUNDLE));
#else
#ifdef __FreeBSD__
	qsl << QLatin1String("/usr/local/share/certs/ca-root-nss.crt");
#else
	qsl << QLatin1String("/etc/pki/tls/certs/ca-bundle.crt");
	qsl << QLatin1String("/etc/ssl/certs/ca-certificates.crt");
#endif
#endif

	foreach(const QString &filename, qsl) {
		QFile f(filename);
		if (f.exists() && f.open(QIODevice::ReadOnly)) {
			QList<QSslCertificate> ql = QSslCertificate::fromDevice(&f, QSsl::Pem);
			ql += QSslCertificate::fromDevice(&f, QSsl::Der);
			if (! ql.isEmpty()) {
				qWarning("SSL: Added CA certificates from '%s'", qPrintable(filename));
				QSslSocket::addDefaultCaCertificates(ql);
			}
		}
	}
#endif // SYSTEM_CA_DIR
#endif // Q_OS_UNIX

	QSet<QByteArray> digests;
	QList<QSslCertificate> ql;
	foreach(const QSslCertificate &crt, QSslSocket::defaultCaCertificates()) {
		QByteArray digest = crt.digest(QCryptographicHash::Sha1);
		if (! digests.contains(digest) && crt.isValid()) {
			ql << crt;
			digests.insert(digest);
		}
	}
	QSslSocket::setDefaultCaCertificates(ql);
#endif // NO_SYSTEM_CA_OVERRIDE

#if QT_VERSION >= 0x040800
	// Don't perform on-demand loading of root certificates
	QSslSocket::addDefaultCaCertificates(QSslSocket::systemCaCertificates());
#endif

#ifdef Q_OS_WIN
	// Work around issue #1271.
	// Skype's click-to-call feature creates an enormous
	// amount of certificates in the Root CA store.
	{
		QSslConfiguration sslCfg = QSslConfiguration::defaultConfiguration();
		QList<QSslCertificate> caList = sslCfg.caCertificates();

		QList<QSslCertificate> filteredCaList;
		foreach (QSslCertificate cert, caList) {
#if QT_VERSION >= 0x050000
			QStringList orgs = cert.subjectInfo(QSslCertificate::Organization);
			bool skip = false;
			foreach (QString ou, orgs) {
				if (ou.contains(QLatin1String("Skype"), Qt::CaseInsensitive)) {
					skip = true;
					break;
				}
			}
			if (skip) {
				continue;
			}
#else
			QString ou = cert.subjectInfo(QSslCertificate::Organization);
			if (ou.contains(QLatin1String("Skype"), Qt::CaseInsensitive)) {
				continue;
			}
#endif
			filteredCaList.append(cert);
		}

		sslCfg.setCaCertificates(filteredCaList);
		QSslConfiguration::setDefaultConfiguration(sslCfg);

		qWarning("SSL: CA certificate filter applied. Filtered size: %i, original size: %i", filteredCaList.size(), caList.size());
	}
#endif
}
<|endoftext|>


<commit_before>// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
#include "paintwidgets.hh"
#include "factory.hh"
#include "painter.hh"

#define CHECK_CAIRO_STATUS(status)      do {    \
  cairo_status_t ___s = (status);               \
  if (___s != CAIRO_STATUS_SUCCESS)             \
    RAPICORN_DIAG ("%s: %s", cairo_status_to_string (___s), #status);   \
  } while (0)

namespace Rapicorn {

// == ArrowImpl ==
ArrowImpl::ArrowImpl() :
  dir_ (Direction::RIGHT)
{}

ArrowImpl::~ArrowImpl()
{}

Direction
ArrowImpl::arrow_dir () const
{
  return dir_;
}

void
ArrowImpl::arrow_dir (Direction dir)
{
  dir_ = dir;
  expose();
  changed ("arrow_dir");
}

static DataKey<SizePolicy> size_policy_key;

SizePolicy
ArrowImpl::size_policy () const
{
  SizePolicy spol = get_data (&size_policy_key);
  return spol;
}

void
ArrowImpl::size_policy (SizePolicy spol)
{
  if (spol == 0)
    delete_data (&size_policy_key);
  else
    set_data (&size_policy_key, spol);
  invalidate_size();
  changed ("size_policy");
}

void
ArrowImpl::size_request (Requisition &requisition)
{
  requisition.width = 3;
  requisition.height = 3;
}

void
ArrowImpl::size_allocate (Allocation area, bool changed)
{
  SizePolicy spol = size_policy();
  if (spol == SizePolicy::WIDTH_FROM_HEIGHT)
    tune_requisition (area.height, -1);
  else if (spol == SizePolicy::HEIGHT_FROM_WIDTH)
    tune_requisition (-1, area.width);
}

void
ArrowImpl::render (RenderContext &rcontext, const IRect &rect)
{
  IRect ia = allocation();
  int x = ia.x, y = ia.y, width = ia.width, height = ia.height;
  if (width >= 2 && height >= 2)
    {
      cairo_t *cr = cairo_context (rcontext, rect);
      CPainter painter (cr);
      painter.draw_dir_arrow (x, y, width, height, foreground(), dir_);
    }
}

static const WidgetFactory<ArrowImpl> arrow_factory ("Rapicorn::Arrow");

// == DotGrid ==
DotGridImpl::DotGridImpl() :
  normal_dot_ (DrawFrame::IN),
  active_dot_ (DrawFrame::IN),
  n_hdots_ (1), n_vdots_ (1),
  right_padding_dots_ (0), top_padding_dots_ (0),
  left_padding_dots_ (0), bottom_padding_dots_ (0)
{}

DotGridImpl::~DotGridImpl()
{}

DrawFrame
DotGridImpl::dot_type () const
{
  RAPICORN_ASSERT_UNREACHED();
}

void
DotGridImpl::dot_type (DrawFrame ft)
{
  normal_dot (ft);
  active_dot (ft);
}

DrawFrame
DotGridImpl::current_dot ()
{
  return ancestry_active() ? active_dot() : normal_dot();
}

static inline int
u31 (int v)
{
  return CLAMP (v, 0, INT_MAX);
}

void
DotGridImpl::active_dot (DrawFrame ft)
{
  active_dot_ = ft;
  expose();
  changed ("active_dot");
}

DrawFrame
DotGridImpl::active_dot () const
{
  return active_dot_;
}

void
DotGridImpl::normal_dot (DrawFrame ft)
{
  normal_dot_ = ft;
  expose();
  changed ("normal_dot");
}

DrawFrame
DotGridImpl::normal_dot () const
{
  return normal_dot_;
}

void
DotGridImpl::n_hdots (int num)
{
  n_hdots_ = u31 (num);
  expose();
  changed ("n_hdots");
}

int
DotGridImpl::n_hdots () const
{
  return n_hdots_;
}

void
DotGridImpl::n_vdots (int num)
{
  n_vdots_ = u31 (num);
  expose();
  changed ("n_vdots");
}

int
DotGridImpl::n_vdots () const
{
  return n_vdots_;
}

int
DotGridImpl::right_padding_dots () const
{
  return right_padding_dots_;
}

void
DotGridImpl::right_padding_dots (int c)
{
  right_padding_dots_ = u31 (c);
  expose();
  changed ("right_padding_dots");
}

int
DotGridImpl::top_padding_dots () const
{
  return top_padding_dots_;
}

void
DotGridImpl::top_padding_dots (int c)
{
  top_padding_dots_ = u31 (c);
  expose();
  changed ("top_padding_dots");
}

int
DotGridImpl::left_padding_dots () const
{
  return left_padding_dots_;
}

void
DotGridImpl::left_padding_dots (int c)
{
  left_padding_dots_ = u31 (c);
  expose();
  changed ("left_padding_dots");
}

int
DotGridImpl::bottom_padding_dots () const
{
  return bottom_padding_dots_;
}

void
DotGridImpl::bottom_padding_dots (int c)
{
  bottom_padding_dots_ = u31 (c);
  expose();
  changed ("bottom_padding_dots");
}

void
DotGridImpl::size_request (Requisition &requisition)
{
  const uint ythick = 1, xthick = 1;
  requisition.width = n_hdots_ * (xthick + xthick) + MAX (n_hdots_ - 1, 0) * xthick;
  requisition.height = n_vdots_ * (ythick + ythick) + MAX (n_vdots_ - 1, 0) * ythick;
  requisition.width += (right_padding_dots_ + left_padding_dots_) * 3 * xthick;
  requisition.height += (top_padding_dots_ + bottom_padding_dots_) * 3 * ythick;
}

void
DotGridImpl::size_allocate (Allocation area, bool changed)
{}

void
DotGridImpl::render (RenderContext &rcontext, const IRect &rect)
{
  const int ythick = 1, xthick = 1;
  int n_hdots = n_hdots_, n_vdots = n_vdots_;
  const IRect ia = allocation();
  int x = ia.x, y = ia.y, width = ia.width, height = ia.height;
  const int rq_width = n_hdots_ * (xthick + xthick) + MAX (n_hdots - 1, 0) * xthick;
  const int rq_height = n_vdots_ * (ythick + ythick) + MAX (n_vdots - 1, 0) * ythick;
  /* split up extra width */
  const uint hpadding = right_padding_dots_ + left_padding_dots_;
  const double halign = hpadding ? left_padding_dots_ * 1.0 / hpadding : 0.5;
  if (rq_width < width)
    x += ifloor ((width - rq_width) * halign);
  /* split up extra height */
  const uint vpadding = top_padding_dots_ + bottom_padding_dots_;
  const double valign = vpadding ? bottom_padding_dots_ * 1.0 / vpadding : 0.5;
  if (rq_height < height)
    y += ifloor ((height - rq_height) * valign);
  /* draw dots */
  if (width >= 2 * xthick && height >= 2 * ythick && n_hdots && n_vdots)
    {
      /* limit n_hdots */
      if (rq_width > width)
        {
          const int w = width - 2 * xthick;     // dot1
          n_hdots = 1 + w / (3 * xthick);
        }
      /* limit n_vdots */
      if (rq_height > height)
        {
          const int h = height - 2 * ythick;    // dot1
          n_vdots = 1 + h / (3 * ythick);
        }
      cairo_t *cr = cairo_context (rcontext, rect);
      CPainter rp (cr);
      for (int j = 0; j < n_vdots; j++)
        {
          int xtmp = 0;
          for (int i = 0; i < n_hdots; i++)
            {
              rp.draw_shaded_rect (x + xtmp, y + 2 * ythick - 1, dark_shadow(),
                                   x + xtmp + 2 * xthick - 1, y, light_glint());
              xtmp += 3 * xthick;
            }
          y += 3 * ythick;
        }
    }
}

static const WidgetFactory<DotGridImpl> dot_grid_factory ("Rapicorn::DotGrid");

// == DrawableImpl ==
DrawableImpl::DrawableImpl() :
  x_ (0), y_ (0)
{}

void
DrawableImpl::size_request (Requisition &requisition)
{
  requisition.width = 320;
  requisition.height = 200;
}

void
DrawableImpl::size_allocate (Allocation area, bool changed)
{
  if (false) // clear out, can lead to flicker
    {
      pixbuf_ = Pixbuf();
      x_ = 0;
      y_ = 0;
    }
  sig_redraw.emit (area.x, area.y, area.width, area.height);
}

void
DrawableImpl::draw_rect (int x, int y, const Pixbuf &pixbuf)
{
  const Allocation &area = allocation();
  const size_t rowstride = pixbuf.width();
  if (x >= area.x && y >= area.y &&
      x + pixbuf.width() <= area.x + area.width &&
      y + pixbuf.height() <= area.y + area.height &&
      rowstride * pixbuf.height() <= pixbuf.pixels.size())
    {
      x_ = x;
      y_ = y;
      pixbuf_ = pixbuf;
    }
  else if (pixbuf_.width() > 0)
    {
      pixbuf_ = Pixbuf();
      x_ = 0;
      y_ = 0;
    }
  expose();
}

void
DrawableImpl::render (RenderContext &rcontext, const IRect &rect)
{
  const uint size = 10;
  const Allocation &area = allocation();
  cairo_t *cr = cairo_context (rcontext, rect);
  // checkerboard pattern
  if (true)
    {
      cairo_save (cr);
      cairo_surface_t *ps = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR, 2 * size, 2 * size);
      cairo_t *pc = cairo_create (ps);
      cairo_set_source_rgb (pc, 1.0, 1.0, 1.0);
      cairo_rectangle (pc,    0,    0, size, size);
      cairo_rectangle (pc, size, size, size, size);
      cairo_fill (pc);
      cairo_set_source_rgb (pc, 0.9, 0.9, 0.9);
      cairo_rectangle (pc,    0, size, size, size);
      cairo_rectangle (pc, size,    0, size, size);
      cairo_fill (pc);
      cairo_destroy (pc);
      cairo_pattern_t *pat = cairo_pattern_create_for_surface (ps);
      cairo_surface_destroy (ps);
      cairo_pattern_set_extend (pat, CAIRO_EXTEND_REPEAT);
      // render pattern
      cairo_rectangle (cr, area.x, area.y, area.width, area.height);
      cairo_clip (cr);
      cairo_translate (cr, area.x, area.y + area.height);
      cairo_set_source (cr, pat);
      cairo_paint (cr);
      cairo_pattern_destroy (pat);
      cairo_restore (cr);
    }
  // handle user draw
  if (pixbuf_.width() > 0 && pixbuf_.height() > 0)
    {
      const int rowstride = pixbuf_.width();
      cairo_surface_t *surface = cairo_image_surface_create_for_data ((uint8*) pixbuf_.pixels.data(), CAIRO_FORMAT_ARGB32,
                                                                      pixbuf_.width(), pixbuf_.height(), rowstride * 4);
      CHECK_CAIRO_STATUS (cairo_surface_status (surface));
      cairo_set_source_surface (cr, surface, x_, y_);
      cairo_paint (cr);
      cairo_surface_destroy (surface);
    }
}

static const WidgetFactory<DrawableImpl> drawable_factory ("Rapicorn::Drawable");

} // Rapicorn
<commit_msg>UI: DrawableImpl: use invalidate_content() to avoid missing exposes<commit_after>// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
#include "paintwidgets.hh"
#include "factory.hh"
#include "painter.hh"

#define CHECK_CAIRO_STATUS(status)      do {    \
  cairo_status_t ___s = (status);               \
  if (___s != CAIRO_STATUS_SUCCESS)             \
    RAPICORN_DIAG ("%s: %s", cairo_status_to_string (___s), #status);   \
  } while (0)

namespace Rapicorn {

// == ArrowImpl ==
ArrowImpl::ArrowImpl() :
  dir_ (Direction::RIGHT)
{}

ArrowImpl::~ArrowImpl()
{}

Direction
ArrowImpl::arrow_dir () const
{
  return dir_;
}

void
ArrowImpl::arrow_dir (Direction dir)
{
  dir_ = dir;
  expose();
  changed ("arrow_dir");
}

static DataKey<SizePolicy> size_policy_key;

SizePolicy
ArrowImpl::size_policy () const
{
  SizePolicy spol = get_data (&size_policy_key);
  return spol;
}

void
ArrowImpl::size_policy (SizePolicy spol)
{
  if (spol == 0)
    delete_data (&size_policy_key);
  else
    set_data (&size_policy_key, spol);
  invalidate_size();
  changed ("size_policy");
}

void
ArrowImpl::size_request (Requisition &requisition)
{
  requisition.width = 3;
  requisition.height = 3;
}

void
ArrowImpl::size_allocate (Allocation area, bool changed)
{
  SizePolicy spol = size_policy();
  if (spol == SizePolicy::WIDTH_FROM_HEIGHT)
    tune_requisition (area.height, -1);
  else if (spol == SizePolicy::HEIGHT_FROM_WIDTH)
    tune_requisition (-1, area.width);
}

void
ArrowImpl::render (RenderContext &rcontext, const IRect &rect)
{
  IRect ia = allocation();
  int x = ia.x, y = ia.y, width = ia.width, height = ia.height;
  if (width >= 2 && height >= 2)
    {
      cairo_t *cr = cairo_context (rcontext, rect);
      CPainter painter (cr);
      painter.draw_dir_arrow (x, y, width, height, foreground(), dir_);
    }
}

static const WidgetFactory<ArrowImpl> arrow_factory ("Rapicorn::Arrow");

// == DotGrid ==
DotGridImpl::DotGridImpl() :
  normal_dot_ (DrawFrame::IN),
  active_dot_ (DrawFrame::IN),
  n_hdots_ (1), n_vdots_ (1),
  right_padding_dots_ (0), top_padding_dots_ (0),
  left_padding_dots_ (0), bottom_padding_dots_ (0)
{}

DotGridImpl::~DotGridImpl()
{}

DrawFrame
DotGridImpl::dot_type () const
{
  RAPICORN_ASSERT_UNREACHED();
}

void
DotGridImpl::dot_type (DrawFrame ft)
{
  normal_dot (ft);
  active_dot (ft);
}

DrawFrame
DotGridImpl::current_dot ()
{
  return ancestry_active() ? active_dot() : normal_dot();
}

static inline int
u31 (int v)
{
  return CLAMP (v, 0, INT_MAX);
}

void
DotGridImpl::active_dot (DrawFrame ft)
{
  active_dot_ = ft;
  expose();
  changed ("active_dot");
}

DrawFrame
DotGridImpl::active_dot () const
{
  return active_dot_;
}

void
DotGridImpl::normal_dot (DrawFrame ft)
{
  normal_dot_ = ft;
  expose();
  changed ("normal_dot");
}

DrawFrame
DotGridImpl::normal_dot () const
{
  return normal_dot_;
}

void
DotGridImpl::n_hdots (int num)
{
  n_hdots_ = u31 (num);
  expose();
  changed ("n_hdots");
}

int
DotGridImpl::n_hdots () const
{
  return n_hdots_;
}

void
DotGridImpl::n_vdots (int num)
{
  n_vdots_ = u31 (num);
  expose();
  changed ("n_vdots");
}

int
DotGridImpl::n_vdots () const
{
  return n_vdots_;
}

int
DotGridImpl::right_padding_dots () const
{
  return right_padding_dots_;
}

void
DotGridImpl::right_padding_dots (int c)
{
  right_padding_dots_ = u31 (c);
  expose();
  changed ("right_padding_dots");
}

int
DotGridImpl::top_padding_dots () const
{
  return top_padding_dots_;
}

void
DotGridImpl::top_padding_dots (int c)
{
  top_padding_dots_ = u31 (c);
  expose();
  changed ("top_padding_dots");
}

int
DotGridImpl::left_padding_dots () const
{
  return left_padding_dots_;
}

void
DotGridImpl::left_padding_dots (int c)
{
  left_padding_dots_ = u31 (c);
  expose();
  changed ("left_padding_dots");
}

int
DotGridImpl::bottom_padding_dots () const
{
  return bottom_padding_dots_;
}

void
DotGridImpl::bottom_padding_dots (int c)
{
  bottom_padding_dots_ = u31 (c);
  expose();
  changed ("bottom_padding_dots");
}

void
DotGridImpl::size_request (Requisition &requisition)
{
  const uint ythick = 1, xthick = 1;
  requisition.width = n_hdots_ * (xthick + xthick) + MAX (n_hdots_ - 1, 0) * xthick;
  requisition.height = n_vdots_ * (ythick + ythick) + MAX (n_vdots_ - 1, 0) * ythick;
  requisition.width += (right_padding_dots_ + left_padding_dots_) * 3 * xthick;
  requisition.height += (top_padding_dots_ + bottom_padding_dots_) * 3 * ythick;
}

void
DotGridImpl::size_allocate (Allocation area, bool changed)
{}

void
DotGridImpl::render (RenderContext &rcontext, const IRect &rect)
{
  const int ythick = 1, xthick = 1;
  int n_hdots = n_hdots_, n_vdots = n_vdots_;
  const IRect ia = allocation();
  int x = ia.x, y = ia.y, width = ia.width, height = ia.height;
  const int rq_width = n_hdots_ * (xthick + xthick) + MAX (n_hdots - 1, 0) * xthick;
  const int rq_height = n_vdots_ * (ythick + ythick) + MAX (n_vdots - 1, 0) * ythick;
  /* split up extra width */
  const uint hpadding = right_padding_dots_ + left_padding_dots_;
  const double halign = hpadding ? left_padding_dots_ * 1.0 / hpadding : 0.5;
  if (rq_width < width)
    x += ifloor ((width - rq_width) * halign);
  /* split up extra height */
  const uint vpadding = top_padding_dots_ + bottom_padding_dots_;
  const double valign = vpadding ? bottom_padding_dots_ * 1.0 / vpadding : 0.5;
  if (rq_height < height)
    y += ifloor ((height - rq_height) * valign);
  /* draw dots */
  if (width >= 2 * xthick && height >= 2 * ythick && n_hdots && n_vdots)
    {
      /* limit n_hdots */
      if (rq_width > width)
        {
          const int w = width - 2 * xthick;     // dot1
          n_hdots = 1 + w / (3 * xthick);
        }
      /* limit n_vdots */
      if (rq_height > height)
        {
          const int h = height - 2 * ythick;    // dot1
          n_vdots = 1 + h / (3 * ythick);
        }
      cairo_t *cr = cairo_context (rcontext, rect);
      CPainter rp (cr);
      for (int j = 0; j < n_vdots; j++)
        {
          int xtmp = 0;
          for (int i = 0; i < n_hdots; i++)
            {
              rp.draw_shaded_rect (x + xtmp, y + 2 * ythick - 1, dark_shadow(),
                                   x + xtmp + 2 * xthick - 1, y, light_glint());
              xtmp += 3 * xthick;
            }
          y += 3 * ythick;
        }
    }
}

static const WidgetFactory<DotGridImpl> dot_grid_factory ("Rapicorn::DotGrid");

// == DrawableImpl ==
DrawableImpl::DrawableImpl() :
  x_ (0), y_ (0)
{}

void
DrawableImpl::size_request (Requisition &requisition)
{
  requisition.width = 320;
  requisition.height = 200;
}

void
DrawableImpl::size_allocate (Allocation area, bool changed)
{
  if (false) // clear out, can lead to flicker
    {
      pixbuf_ = Pixbuf();
      x_ = 0;
      y_ = 0;
    }
  sig_redraw.emit (area.x, area.y, area.width, area.height);
}

void
DrawableImpl::draw_rect (int x, int y, const Pixbuf &pixbuf)
{
  const Allocation &area = allocation();
  const size_t rowstride = pixbuf.width();
  if (x >= area.x && y >= area.y &&
      x + pixbuf.width() <= area.x + area.width &&
      y + pixbuf.height() <= area.y + area.height &&
      rowstride * pixbuf.height() <= pixbuf.pixels.size())
    {
      x_ = x;
      y_ = y;
      pixbuf_ = pixbuf;
    }
  else if (pixbuf_.width() > 0)
    {
      pixbuf_ = Pixbuf();
      x_ = 0;
      y_ = 0;
    }
  invalidate_content();
}

void
DrawableImpl::render (RenderContext &rcontext, const IRect &rect)
{
  const uint size = 10;
  const Allocation &area = allocation();
  cairo_t *cr = cairo_context (rcontext, rect);
  // checkerboard pattern
  if (true)
    {
      cairo_save (cr);
      cairo_surface_t *ps = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR, 2 * size, 2 * size);
      cairo_t *pc = cairo_create (ps);
      cairo_set_source_rgb (pc, 1.0, 1.0, 1.0);
      cairo_rectangle (pc,    0,    0, size, size);
      cairo_rectangle (pc, size, size, size, size);
      cairo_fill (pc);
      cairo_set_source_rgb (pc, 0.9, 0.9, 0.9);
      cairo_rectangle (pc,    0, size, size, size);
      cairo_rectangle (pc, size,    0, size, size);
      cairo_fill (pc);
      cairo_destroy (pc);
      cairo_pattern_t *pat = cairo_pattern_create_for_surface (ps);
      cairo_surface_destroy (ps);
      cairo_pattern_set_extend (pat, CAIRO_EXTEND_REPEAT);
      // render pattern
      cairo_rectangle (cr, area.x, area.y, area.width, area.height);
      cairo_clip (cr);
      cairo_translate (cr, area.x, area.y + area.height);
      cairo_set_source (cr, pat);
      cairo_paint (cr);
      cairo_pattern_destroy (pat);
      cairo_restore (cr);
    }
  // handle user draw
  if (pixbuf_.width() > 0 && pixbuf_.height() > 0)
    {
      const int rowstride = pixbuf_.width();
      cairo_surface_t *surface = cairo_image_surface_create_for_data ((uint8*) pixbuf_.pixels.data(), CAIRO_FORMAT_ARGB32,
                                                                      pixbuf_.width(), pixbuf_.height(), rowstride * 4);
      CHECK_CAIRO_STATUS (cairo_surface_status (surface));
      cairo_set_source_surface (cr, surface, x_, y_);
      cairo_paint (cr);
      cairo_surface_destroy (surface);
    }
}

static const WidgetFactory<DrawableImpl> drawable_factory ("Rapicorn::Drawable");

} // Rapicorn
<|endoftext|>


<commit_before>// Slit.hh for Fluxbox
// Copyright (c) 2002 - 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
//
// Slit.hh for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

/// $Id: Slit.hh,v 1.19 2003/02/18 15:11:08 rathnor Exp $

#ifndef	 SLIT_HH
#define	 SLIT_HH

#include "Menu.hh"
#include "FbWindow.hh"
#include "Timer.hh"
#include "XLayerItem.hh"
#include "LayerMenu.hh"

#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include <list>
#include <string>
#include <memory>
class BScreen;
class SlitClient;

/// Handles dock apps
class Slit : public FbTk::TimeoutHandler, public FbTk::EventHandler {
public:

    /**
       Client alignment
    */
    enum Direction { VERTICAL = 1, HORIZONTAL };
    /**
       Screen placement
    */
    enum Placement { TOPLEFT = 1, CENTERLEFT, BOTTOMLEFT, TOPCENTER, BOTTOMCENTER,
           TOPRIGHT, CENTERRIGHT, BOTTOMRIGHT };

    explicit Slit(BScreen &screen, FbTk::XLayer &layer, const char *filename = 0);
    virtual ~Slit();

    inline bool isHidden() const { return hidden; }
    inline bool doAutoHide() const { return do_auto_hide; }
    inline Direction direction() const { return m_direction; }
    inline Placement placement() const { return m_placement; }
    FbTk::Menu &menu() { return slitmenu; }

    inline Window getWindowID() const { return frame.window.window(); }

    inline int x() const { return ((hidden) ? frame.x_hidden : frame.x); }
    inline int y() const { return ((hidden) ? frame.y_hidden : frame.y); }

    inline unsigned int width() const { return frame.width; }
    inline unsigned int height() const { return frame.height; }

    void setDirection(Direction dir);
    void setPlacement(Placement place);
    void setAutoHide(bool val);
    void addClient(Window clientwin);
    void removeClient(Window clientwin, bool = true);
    void reconfigure();
    void reposition();
    void shutdown();
    /// save clients name in a file
    void saveClientList();
    /// cycle slit clients up one step
    void cycleClientsUp();
    /// cycle slit clients down one step
    void cycleClientsDown();

    BScreen *screen() { return m_screen; }
    const BScreen *screen() const { return m_screen; }
    /**
       @name eventhandlers
    */
    //@{
    void handleEvent(XEvent &event);
    void buttonPressEvent(XButtonEvent &event);
    void enterNotifyEvent(XCrossingEvent &event);
    void leaveNotifyEvent(XCrossingEvent &event);
    void configureRequestEvent(XConfigureRequestEvent &event);
    //@}

    void moveToLayer(int layernum) { m_layeritem->moveToLayer(layernum); }
    FbTk::XLayerItem &getLayerItem() { return *m_layeritem; }

    virtual void timeout();

private:
    void setupMenu();

    void removeClient(SlitClient *client, bool remap, bool destroy);
    void loadClientList(const char *filename);
    void updateClientmenu();

    bool hidden, do_auto_hide;
    Direction m_direction;
    Placement m_placement;

    BScreen *m_screen;
    FbTk::Timer timer;

    typedef std::list<SlitClient *> SlitClients;

    SlitClients clientList;
    FbTk::Menu slitmenu, placement_menu, clientlist_menu;
    LayerMenu<Slit> *slit_layermenu;
    std::string clientListPath;
    std::string m_filename;

    struct frame {
        Pixmap pixmap;
        FbTk::FbWindow window;

        int x, y, x_hidden, y_hidden;
        unsigned int width, height;
    } frame;
    // for KDE
    Atom kwm1_dockwindow, kwm2_dockwindow;

    FbTk::XLayerItem *m_layeritem;
};

#endif // SLIT_HH
<commit_msg>minor cleaning<commit_after>// Slit.hh for Fluxbox
// Copyright (c) 2002 - 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
//
// Slit.hh for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

/// $Id: Slit.hh,v 1.20 2003/02/20 16:38:17 fluxgen Exp $

#ifndef	 SLIT_HH
#define	 SLIT_HH

#include "Menu.hh"
#include "FbWindow.hh"
#include "Timer.hh"
#include "XLayerItem.hh"
#include "LayerMenu.hh"

#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include <list>
#include <string>
#include <memory>

class BScreen;
class SlitClient;

/// Handles dock apps
class Slit : public FbTk::TimeoutHandler, public FbTk::EventHandler {
public:

    /**
       Client alignment
    */
    enum Direction { VERTICAL = 1, HORIZONTAL };
    /**
       Screen placement
    */
    enum Placement { TOPLEFT = 1, CENTERLEFT, BOTTOMLEFT, TOPCENTER, BOTTOMCENTER,
           TOPRIGHT, CENTERRIGHT, BOTTOMRIGHT };

    explicit Slit(BScreen &screen, FbTk::XLayer &layer, const char *filename = 0);
    virtual ~Slit();

    inline bool isHidden() const { return hidden; }
    inline bool doAutoHide() const { return do_auto_hide; }
    inline Direction direction() const { return m_direction; }
    inline Placement placement() const { return m_placement; }
    FbTk::Menu &menu() { return slitmenu; }

    inline Window getWindowID() const { return frame.window.window(); }

    inline int x() const { return ((hidden) ? frame.x_hidden : frame.x); }
    inline int y() const { return ((hidden) ? frame.y_hidden : frame.y); }

    inline unsigned int width() const { return frame.width; }
    inline unsigned int height() const { return frame.height; }

    void setDirection(Direction dir);
    void setPlacement(Placement place);
    void setAutoHide(bool val);
    void addClient(Window clientwin);
    void removeClient(Window clientwin, bool = true);
    void reconfigure();
    void reposition();
    void shutdown();
    /// save clients name in a file
    void saveClientList();
    /// cycle slit clients up one step
    void cycleClientsUp();
    /// cycle slit clients down one step
    void cycleClientsDown();

    BScreen &screen() { return m_screen; }
    const BScreen &screen() const { return m_screen; }
    /**
       @name eventhandlers
    */
    //@{
    void handleEvent(XEvent &event);
    void buttonPressEvent(XButtonEvent &event);
    void enterNotifyEvent(XCrossingEvent &event);
    void leaveNotifyEvent(XCrossingEvent &event);
    void configureRequestEvent(XConfigureRequestEvent &event);
    //@}

    void moveToLayer(int layernum) { m_layeritem->moveToLayer(layernum); }
    FbTk::XLayerItem &getLayerItem() { return *m_layeritem; }

    virtual void timeout();

private:
    void setupMenu();

    void removeClient(SlitClient *client, bool remap, bool destroy);
    void loadClientList(const char *filename);
    void updateClientmenu();

    bool hidden, do_auto_hide;
    Direction m_direction;
    Placement m_placement;

    BScreen &m_screen;
    FbTk::Timer timer;

    typedef std::list<SlitClient *> SlitClients;

    SlitClients clientList;
    FbTk::Menu slitmenu, placement_menu, clientlist_menu;
    std::auto_ptr<LayerMenu<Slit> > slit_layermenu;
    std::string clientListPath;
    std::string m_filename;

    struct frame {
        Pixmap pixmap;
        FbTk::FbWindow window;

        int x, y, x_hidden, y_hidden;
        unsigned int width, height;
    } frame;
    // for KDE
    Atom kwm1_dockwindow, kwm2_dockwindow;

    std::auto_ptr<FbTk::XLayerItem> m_layeritem;
};

#endif // SLIT_HH
<|endoftext|>


<commit_before>#include "kaynesgameoflife.hpp"
#include <MINX/Graphics/Color.hpp>
#include <MINX/Graphics/GameWindow.hpp>
#include <MINX/Graphics/TextureBatch.hpp>
#include <MINX/Graphics/ShaderFactory.hpp>

using namespace KayneGameOfLife;
using namespace MINX;
using namespace MINX::Graphics;

bool* map;
TextureBatch* texBatch;
const int tileWidth = 32, tileHeight = 32;

GameOfLife::GameOfLife() : Game()
{
	//This is the constructor. Put stuff here that should happen when the Game is created.

	Game::SetVideoOptions(640, 480, false, "kaynes-game-of-life");
}

void GameOfLife::Initialize()
{
	//Put stuff here that should happen when the Game is initialized.

	GameWindow::sizeLocked = true;
	int width = GameWindow::GetWidth()/tileWidth;
	int height = GameWindow::GetHeight()/tileHeight;
	map = (bool*)malloc(width * height);
	for(int y = 0; y < height; ++y)
	{
		for(int x = 0; x < width; ++x)
		{
			map[y * width + x] = Math::random(0, 1, 2);
		}
	}

	Game::Initialize();

	texBatch = new TextureBatch(ShaderFactory::GetInstance()->GetShaderAtIndex(0));
}

void GameOfLife::LoadContent()
{
	//Put stuff here that loads content for your game.
	Game::LoadContent();
}

void GameOfLife::UnloadContent()
{
	//Put stuff here that unloads content from your game.

	free(map);

	Game::UnloadContent();
}

void GameOfLife::Update(GameTime * gameTime)
{
	//Put stuff here to update the logic in your game each tick.
	Game::Update(gameTime);
}

void GameOfLife::Draw(GameTime * gameTime)
{
	SetRenderTarget(NULL, Graphics::Color::CornflowerBlue);

	int width = GameWindow::GetWidth()/tileWidth;
	int height = GameWindow::GetHeight()/tileHeight;

	for(int y = 0; y < height; ++y)
	{
		for(int x = 0; x < width; ++x)
		{
			texBatch->DrawPrimitiveRectangle(Rectangle(x * tileWidth, y * tileHeight, tileWidth, tileHeight), map[y * width + x] ? Color::Black : Color::Salmon);
		}
	}

	texBatch->DrawLoadedTextures();

	//Put stuff here to draw your game each frame.
	Game::Draw(gameTime);
}<commit_msg>Implemented rules of the game<commit_after>#include "kaynesgameoflife.hpp"
#include <MINX/Graphics/Color.hpp>
#include <MINX/Graphics/GameWindow.hpp>
#include <MINX/Graphics/TextureBatch.hpp>
#include <MINX/Graphics/ShaderFactory.hpp>

using namespace KayneGameOfLife;
using namespace MINX;
using namespace MINX::Graphics;

bool* map;
TextureBatch* texBatch;
const int tileWidth = 16, tileHeight = 16;

double elapsedTime = 0.0;
double timeLimit = 0.5;

bool* updateCells(bool* board, int width, int height);
int calculateLiveNeighbors(bool* board, int x, int y, int width, int height);

GameOfLife::GameOfLife() : Game()
{
	//This is the constructor. Put stuff here that should happen when the Game is created.
	srand(time(NULL));
	Game::SetVideoOptions(640, 480, false, "kaynes-game-of-life");
}

void GameOfLife::Initialize()
{
	//Put stuff here that should happen when the Game is initialized.

	GameWindow::sizeLocked = true;
	int width = GameWindow::GetWidth()/tileWidth;
	int height = GameWindow::GetHeight()/tileHeight;
	map = (bool*)malloc(width * height);
	for(int y = 0; y < height; ++y)
	{
		for(int x = 0; x < width; ++x)
		{
			map[y * width + x] = Math::random(0, 1, 2);
		}
	}

	Game::Initialize();

	texBatch = new TextureBatch(ShaderFactory::GetInstance()->GetShaderAtIndex(0));
}

void GameOfLife::LoadContent()
{
	//Put stuff here that loads content for your game.
	Game::LoadContent();
}

void GameOfLife::UnloadContent()
{
	//Put stuff here that unloads content from your game.

	free(map);

	Game::UnloadContent();
}

void GameOfLife::Update(GameTime * gameTime)
{
	elapsedTime += gameTime->GetDeltaTimeSeconds();

	if(elapsedTime >= timeLimit)
	{
		elapsedTime = 0.0;

		map = updateCells(map, GameWindow::GetWidth()/tileWidth, GameWindow::GetHeight()/tileHeight);
	}
	//Put stuff here to update the logic in your game each tick.
	Game::Update(gameTime);
}

void GameOfLife::Draw(GameTime * gameTime)
{
	SetRenderTarget(NULL, Graphics::Color::CornflowerBlue);

	int width = GameWindow::GetWidth()/tileWidth;
	int height = GameWindow::GetHeight()/tileHeight;

	for(int y = 0; y < height; ++y)
	{
		for(int x = 0; x < width; ++x)
		{
			texBatch->DrawPrimitiveRectangle(
				Rectangle(
					x * tileWidth,
					y * tileHeight,
					tileWidth,
					tileHeight),
				map[y * width + x] ? Color::Black : Color::Salmon);
		}
	}

	texBatch->DrawLoadedTextures();

	//Put stuff here to draw your game each frame.
	Game::Draw(gameTime);
}

bool* updateCells(bool* board, int width, int height)
{
	bool* newBoard = (bool*)malloc(width * height);
	for(int y = 0; y < height; ++y)
	{
		for(int x = 0; x < width; ++x)
		{
			int liveNeighbors = calculateLiveNeighbors(board, x, y, width, height);
			if(board[y * width + x] && (liveNeighbors < 2) || liveNeighbors > 3)
			{
				newBoard[y * width + x] = false;
			}
			else if(board[y * width + x] && liveNeighbors < 4)
			{
				newBoard[y * width + x] = true;
			}
			else if(liveNeighbors == 3)
			{
				newBoard[y * width + x] = true;
			}
			else
			{
				newBoard[y * width + x] = false;
			}
		}
	}
	free(board);
	return newBoard;
}

int calculateLiveNeighbors(bool* board, int x, int y, int width, int height)
{
	int liveCount = 0;
	if(y > 0)
	{
		if(board[(y - 1) * width + x]) ++liveCount;
	}
	if(y > 0 && x > 0)
	{
		if(board[(y - 1) * width + (x - 1)]) ++liveCount;
	}
	if(x > 0)
	{
		if(board[y * width + (x - 1)]) ++liveCount;
	}
	if(x > 0 && y < height)
	{
		if(board[(y + 1) * width + (x - 1)]) ++liveCount;
	}
	if(y < height)
	{
		if(board[(y + 1) * width + x]) ++liveCount;
	}
	if(y < height && x < width)
	{
		if(board[(y + 1) * width + (x + 1)]) ++liveCount;
	}
	if(x < width)
	{
		if(board[y * width + (x + 1)]) ++liveCount;
	}
	if(y > 0 && x < width)
	{
		if(board[(y - 1) * width + (x + 1)]) ++liveCount;
	}
	return liveCount;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <random.h>
#include <scheduler.h>
#include <util/time.h>

#include <boost/thread.hpp>
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(scheduler_tests)

static void microTask(CScheduler& s, boost::mutex& mutex, int& counter, int delta, std::chrono::system_clock::time_point rescheduleTime)
{
    {
        boost::unique_lock<boost::mutex> lock(mutex);
        counter += delta;
    }
    std::chrono::system_clock::time_point noTime = std::chrono::system_clock::time_point::min();
    if (rescheduleTime != noTime) {
        CScheduler::Function f = std::bind(&microTask, std::ref(s), std::ref(mutex), std::ref(counter), -delta + 1, noTime);
        s.schedule(f, rescheduleTime);
    }
}

BOOST_AUTO_TEST_CASE(manythreads)
{
    // Stress test: hundreds of microsecond-scheduled tasks,
    // serviced by 10 threads.
    //
    // So... ten shared counters, which if all the tasks execute
    // properly will sum to the number of tasks done.
    // Each task adds or subtracts a random amount from one of the
    // counters, and then schedules another task 0-1000
    // microseconds in the future to subtract or add from
    // the counter -random_amount+1, so in the end the shared
    // counters should sum to the number of initial tasks performed.
    CScheduler microTasks;

    boost::mutex counterMutex[10];
    int counter[10] = { 0 };
    FastRandomContext rng{/* fDeterministic */ true};
    auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9]
    auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + (int)rc.randrange(1012); }; // [-11, 1000]
    auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + (int)rc.randrange(2001); }; // [-1000, 1000]

    std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
    std::chrono::system_clock::time_point now = start;
    std::chrono::system_clock::time_point first, last;
    size_t nTasks = microTasks.getQueueInfo(first, last);
    BOOST_CHECK(nTasks == 0);

    for (int i = 0; i < 100; ++i) {
        std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
        std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
        int whichCounter = zeroToNine(rng);
        CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
                                             std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
                                             randomDelta(rng), tReschedule);
        microTasks.schedule(f, t);
    }
    nTasks = microTasks.getQueueInfo(first, last);
    BOOST_CHECK(nTasks == 100);
    BOOST_CHECK(first < last);
    BOOST_CHECK(last > now);

    // As soon as these are created they will start running and servicing the queue
    boost::thread_group microThreads;
    for (int i = 0; i < 5; i++)
        microThreads.create_thread(std::bind(&CScheduler::serviceQueue, &microTasks));

    UninterruptibleSleep(std::chrono::microseconds{600});
    now = std::chrono::system_clock::now();

    // More threads and more tasks:
    for (int i = 0; i < 5; i++)
        microThreads.create_thread(std::bind(&CScheduler::serviceQueue, &microTasks));
    for (int i = 0; i < 100; i++) {
        std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
        std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
        int whichCounter = zeroToNine(rng);
        CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
                                             std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
                                             randomDelta(rng), tReschedule);
        microTasks.schedule(f, t);
    }

    // Drain the task queue then exit threads
    microTasks.stop(true);
    microThreads.join_all(); // ... wait until all the threads are done

    int counterSum = 0;
    for (int i = 0; i < 10; i++) {
        BOOST_CHECK(counter[i] != 0);
        counterSum += counter[i];
    }
    BOOST_CHECK_EQUAL(counterSum, 200);
}

BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered)
{
    CScheduler scheduler;

    // each queue should be well ordered with respect to itself but not other queues
    SingleThreadedSchedulerClient queue1(&scheduler);
    SingleThreadedSchedulerClient queue2(&scheduler);

    // create more threads than queues
    // if the queues only permit execution of one task at once then
    // the extra threads should effectively be doing nothing
    // if they don't we'll get out of order behaviour
    boost::thread_group threads;
    for (int i = 0; i < 5; ++i) {
        threads.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler));
    }

    // these are not atomic, if SinglethreadedSchedulerClient prevents
    // parallel execution at the queue level no synchronization should be required here
    int counter1 = 0;
    int counter2 = 0;

    // just simply count up on each queue - if execution is properly ordered then
    // the callbacks should run in exactly the order in which they were enqueued
    for (int i = 0; i < 100; ++i) {
        queue1.AddToProcessQueue([i, &counter1]() {
            bool expectation = i == counter1++;
            assert(expectation);
        });

        queue2.AddToProcessQueue([i, &counter2]() {
            bool expectation = i == counter2++;
            assert(expectation);
        });
    }

    // finish up
    scheduler.stop(true);
    threads.join_all();

    BOOST_CHECK_EQUAL(counter1, 100);
    BOOST_CHECK_EQUAL(counter2, 100);
}

/* disabled for now. See discussion in https://github.com/bitcoin/bitcoin/pull/18174
BOOST_AUTO_TEST_CASE(mockforward)
{
    CScheduler scheduler;

    int counter{0};
    CScheduler::Function dummy = [&counter]{counter++;};

    // schedule jobs for 2, 5 & 8 minutes into the future
    int64_t min_in_milli = 60*1000;
    scheduler.scheduleFromNow(dummy, 2*min_in_milli);
    scheduler.scheduleFromNow(dummy, 5*min_in_milli);
    scheduler.scheduleFromNow(dummy, 8*min_in_milli);

    // check taskQueue
    std::chrono::system_clock::time_point first, last;
    size_t num_tasks = scheduler.getQueueInfo(first, last);
    BOOST_CHECK_EQUAL(num_tasks, 3ul);

    std::thread scheduler_thread([&]() { scheduler.serviceQueue(); });

    // bump the scheduler forward 5 minutes
    scheduler.MockForward(std::chrono::seconds(5*60));

    // ensure scheduler has chance to process all tasks queued for before 1 ms from now.
    scheduler.scheduleFromNow([&scheduler]{ scheduler.stop(false); }, 1);
    scheduler_thread.join();

    // check that the queue only has one job remaining
    num_tasks = scheduler.getQueueInfo(first, last);
    BOOST_CHECK_EQUAL(num_tasks, 1ul);

    // check that the dummy function actually ran
    BOOST_CHECK_EQUAL(counter, 2);

    // check that the time of the remaining job has been updated
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    int delta = std::chrono::duration_cast<std::chrono::seconds>(first - now).count();
    // should be between 2 & 3 minutes from now
    BOOST_CHECK(delta > 2*60 && delta < 3*60);
}
*/

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>scheduler_tests: re-enable mockforward test<commit_after>// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <random.h>
#include <scheduler.h>
#include <util/time.h>

#include <boost/thread.hpp>
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(scheduler_tests)

static void microTask(CScheduler& s, boost::mutex& mutex, int& counter, int delta, std::chrono::system_clock::time_point rescheduleTime)
{
    {
        boost::unique_lock<boost::mutex> lock(mutex);
        counter += delta;
    }
    std::chrono::system_clock::time_point noTime = std::chrono::system_clock::time_point::min();
    if (rescheduleTime != noTime) {
        CScheduler::Function f = std::bind(&microTask, std::ref(s), std::ref(mutex), std::ref(counter), -delta + 1, noTime);
        s.schedule(f, rescheduleTime);
    }
}

BOOST_AUTO_TEST_CASE(manythreads)
{
    // Stress test: hundreds of microsecond-scheduled tasks,
    // serviced by 10 threads.
    //
    // So... ten shared counters, which if all the tasks execute
    // properly will sum to the number of tasks done.
    // Each task adds or subtracts a random amount from one of the
    // counters, and then schedules another task 0-1000
    // microseconds in the future to subtract or add from
    // the counter -random_amount+1, so in the end the shared
    // counters should sum to the number of initial tasks performed.
    CScheduler microTasks;

    boost::mutex counterMutex[10];
    int counter[10] = { 0 };
    FastRandomContext rng{/* fDeterministic */ true};
    auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9]
    auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + (int)rc.randrange(1012); }; // [-11, 1000]
    auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + (int)rc.randrange(2001); }; // [-1000, 1000]

    std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
    std::chrono::system_clock::time_point now = start;
    std::chrono::system_clock::time_point first, last;
    size_t nTasks = microTasks.getQueueInfo(first, last);
    BOOST_CHECK(nTasks == 0);

    for (int i = 0; i < 100; ++i) {
        std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
        std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
        int whichCounter = zeroToNine(rng);
        CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
                                             std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
                                             randomDelta(rng), tReschedule);
        microTasks.schedule(f, t);
    }
    nTasks = microTasks.getQueueInfo(first, last);
    BOOST_CHECK(nTasks == 100);
    BOOST_CHECK(first < last);
    BOOST_CHECK(last > now);

    // As soon as these are created they will start running and servicing the queue
    boost::thread_group microThreads;
    for (int i = 0; i < 5; i++)
        microThreads.create_thread(std::bind(&CScheduler::serviceQueue, &microTasks));

    UninterruptibleSleep(std::chrono::microseconds{600});
    now = std::chrono::system_clock::now();

    // More threads and more tasks:
    for (int i = 0; i < 5; i++)
        microThreads.create_thread(std::bind(&CScheduler::serviceQueue, &microTasks));
    for (int i = 0; i < 100; i++) {
        std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
        std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
        int whichCounter = zeroToNine(rng);
        CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
                                             std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
                                             randomDelta(rng), tReschedule);
        microTasks.schedule(f, t);
    }

    // Drain the task queue then exit threads
    microTasks.stop(true);
    microThreads.join_all(); // ... wait until all the threads are done

    int counterSum = 0;
    for (int i = 0; i < 10; i++) {
        BOOST_CHECK(counter[i] != 0);
        counterSum += counter[i];
    }
    BOOST_CHECK_EQUAL(counterSum, 200);
}

BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered)
{
    CScheduler scheduler;

    // each queue should be well ordered with respect to itself but not other queues
    SingleThreadedSchedulerClient queue1(&scheduler);
    SingleThreadedSchedulerClient queue2(&scheduler);

    // create more threads than queues
    // if the queues only permit execution of one task at once then
    // the extra threads should effectively be doing nothing
    // if they don't we'll get out of order behaviour
    boost::thread_group threads;
    for (int i = 0; i < 5; ++i) {
        threads.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler));
    }

    // these are not atomic, if SinglethreadedSchedulerClient prevents
    // parallel execution at the queue level no synchronization should be required here
    int counter1 = 0;
    int counter2 = 0;

    // just simply count up on each queue - if execution is properly ordered then
    // the callbacks should run in exactly the order in which they were enqueued
    for (int i = 0; i < 100; ++i) {
        queue1.AddToProcessQueue([i, &counter1]() {
            bool expectation = i == counter1++;
            assert(expectation);
        });

        queue2.AddToProcessQueue([i, &counter2]() {
            bool expectation = i == counter2++;
            assert(expectation);
        });
    }

    // finish up
    scheduler.stop(true);
    threads.join_all();

    BOOST_CHECK_EQUAL(counter1, 100);
    BOOST_CHECK_EQUAL(counter2, 100);
}

BOOST_AUTO_TEST_CASE(mockforward)
{
    CScheduler scheduler;

    int counter{0};
    CScheduler::Function dummy = [&counter]{counter++;};

    // schedule jobs for 2, 5 & 8 minutes into the future
    int64_t min_in_milli = 60*1000;
    scheduler.scheduleFromNow(dummy, 2*min_in_milli);
    scheduler.scheduleFromNow(dummy, 5*min_in_milli);
    scheduler.scheduleFromNow(dummy, 8*min_in_milli);

    // check taskQueue
    std::chrono::system_clock::time_point first, last;
    size_t num_tasks = scheduler.getQueueInfo(first, last);
    BOOST_CHECK_EQUAL(num_tasks, 3ul);

    std::thread scheduler_thread([&]() { scheduler.serviceQueue(); });

    // bump the scheduler forward 5 minutes
    scheduler.MockForward(std::chrono::seconds(5*60));

    // ensure scheduler has chance to process all tasks queued for before 1 ms from now.
    scheduler.scheduleFromNow([&scheduler]{ scheduler.stop(false); }, 1);
    scheduler_thread.join();

    // check that the queue only has one job remaining
    num_tasks = scheduler.getQueueInfo(first, last);
    BOOST_CHECK_EQUAL(num_tasks, 1ul);

    // check that the dummy function actually ran
    BOOST_CHECK_EQUAL(counter, 2);

    // check that the time of the remaining job has been updated
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    int delta = std::chrono::duration_cast<std::chrono::seconds>(first - now).count();
    // should be between 2 & 3 minutes from now
    BOOST_CHECK(delta > 2*60 && delta < 3*60);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#include "precompiled_reportdesign.hxx"
#include "ReportDrawPage.hxx"
#include "RptObject.hxx"
#include "RptModel.hxx"
#include "RptDef.hxx"
#include "corestrings.hrc"
#include <comphelper/mimeconfighelper.hxx>
#include <comphelper/classids.hxx>
#include <comphelper/embeddedobjectcontainer.hxx>
#include <comphelper/documentconstants.hxx>

#include <svx/svdmodel.hxx>
#include <com/sun/star/report/XFixedLine.hpp>
#include <com/sun/star/beans/NamedValue.hpp>

#include <tools/diagnose_ex.h>
#include <svx/unoshape.hxx>

namespace reportdesign
{
    using namespace ::com::sun::star;
    using namespace rptui;

OReportDrawPage::OReportDrawPage(SdrPage* _pPage
                                 ,const uno::Reference< report::XSection >& _xSection)
: SvxDrawPage(_pPage)
,m_xSection(_xSection)
{
}

SdrObject* OReportDrawPage::_CreateSdrObject( const uno::Reference< drawing::XShape > & xDescr ) throw ()
{
    uno::Reference< report::XReportComponent> xReportComponent(xDescr,uno::UNO_QUERY);
    if ( xReportComponent.is() )
        return OObjectBase::createObject(xReportComponent);
    return SvxDrawPage::_CreateSdrObject( xDescr );
}

uno::Reference< drawing::XShape >  OReportDrawPage::_CreateShape( SdrObject *pObj ) const throw ()
{
    OObjectBase* pBaseObj = dynamic_cast<OObjectBase*>(pObj);
    if ( !pBaseObj )
        return SvxDrawPage::_CreateShape( pObj );

    uno::Reference< report::XSection> xSection = m_xSection;
    uno::Reference< lang::XMultiServiceFactory> xFactory;
    if ( xSection.is() )
        xFactory.set(xSection->getReportDefinition(),uno::UNO_QUERY);
    uno::Reference< drawing::XShape > xRet;
    uno::Reference< drawing::XShape > xShape;
    if ( xFactory.is() )
    {
        bool bChangeOrientation = false;
        ::rtl::OUString sServiceName = pBaseObj->getServiceName();
        OSL_ENSURE(sServiceName.getLength(),"No Service Name given!");

        if ( pObj->ISA(OUnoObject) )
        {
            OUnoObject* pUnoObj = dynamic_cast<OUnoObject*>(pObj);
            if ( pUnoObj->GetObjIdentifier() == OBJ_DLG_FIXEDTEXT )
            {
                uno::Reference<beans::XPropertySet> xControlModel(pUnoObj->GetUnoControlModel(),uno::UNO_QUERY);
                if ( xControlModel.is() )
                    xControlModel->setPropertyValue( PROPERTY_MULTILINE,uno::makeAny(sal_True));
            }
            else
                bChangeOrientation = pUnoObj->GetObjIdentifier() == OBJ_DLG_HFIXEDLINE;
            SvxShapeControl* pShape = new SvxShapeControl( pObj );
            xShape.set(*pShape,uno::UNO_QUERY);
            pShape->setShapeKind(pObj->GetObjIdentifier());
        }
        else if ( pObj->ISA(OCustomShape) )
        {
            SvxCustomShape* pShape = new SvxCustomShape( pObj );
            uno::Reference < drawing::XEnhancedCustomShapeDefaulter > xShape2 = pShape;
            xShape.set(xShape2,uno::UNO_QUERY);
            pShape->setShapeKind(pObj->GetObjIdentifier());
        }
        else if ( pObj->ISA(SdrOle2Obj) )
        {
            SdrOle2Obj* pOle2Obj = dynamic_cast<SdrOle2Obj*>(pObj);
            if ( !pOle2Obj->GetObjRef().is() )
            {
                sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
                uno::Reference < embed::XEmbeddedObject > xObj;
                ::rtl::OUString sName;
                xObj = pObj->GetModel()->GetPersist()->getEmbeddedObjectContainer().CreateEmbeddedObject(
                    ::comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(
                    ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("80243D39-6741-46C5-926E-069164FF87BB"))), sName );
                OSL_ENSURE(xObj.is(),"Embedded Object could not be created!");

                /**************************************************
                * Das leere OLE-Objekt bekommt ein neues IPObj
                **************************************************/
                pObj->SetEmptyPresObj(sal_False);
                pOle2Obj->SetOutlinerParaObject(NULL);
                pOle2Obj->SetObjRef(xObj);
                pOle2Obj->SetPersistName(sName);
                pOle2Obj->SetName(sName);
                pOle2Obj->SetAspect(nAspect);
                Rectangle aRect = pOle2Obj->GetLogicRect();

                Size aTmp = aRect.GetSize();
                awt::Size aSz( aTmp.Width(), aTmp.Height() );
                xObj->setVisualAreaSize( nAspect, aSz );
            }
            SvxOle2Shape* pShape = new SvxOle2Shape( pObj );
            xShape.set(*pShape,uno::UNO_QUERY);
            pShape->setShapeKind(pObj->GetObjIdentifier());
        }

        if ( !xShape.is() )
            xShape.set( SvxDrawPage::_CreateShape( pObj ) );

        try
        {
            OReportModel* pRptModel = static_cast<OReportModel*>(pObj->GetModel());
            xRet.set( pRptModel->createShape(sServiceName,xShape,bChangeOrientation ? 0 : 1), uno::UNO_QUERY_THROW );
        }
        catch( const uno::Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    return xRet;
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Eliminate ambiguous conversion to cppu::OWeakObject<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#include "precompiled_reportdesign.hxx"
#include "ReportDrawPage.hxx"
#include "RptObject.hxx"
#include "RptModel.hxx"
#include "RptDef.hxx"
#include "corestrings.hrc"
#include <comphelper/mimeconfighelper.hxx>
#include <comphelper/classids.hxx>
#include <comphelper/embeddedobjectcontainer.hxx>
#include <comphelper/documentconstants.hxx>

#include <svx/svdmodel.hxx>
#include <com/sun/star/report/XFixedLine.hpp>
#include <com/sun/star/beans/NamedValue.hpp>

#include <tools/diagnose_ex.h>
#include <svx/unoshape.hxx>

namespace reportdesign
{
    using namespace ::com::sun::star;
    using namespace rptui;

OReportDrawPage::OReportDrawPage(SdrPage* _pPage
                                 ,const uno::Reference< report::XSection >& _xSection)
: SvxDrawPage(_pPage)
,m_xSection(_xSection)
{
}

SdrObject* OReportDrawPage::_CreateSdrObject( const uno::Reference< drawing::XShape > & xDescr ) throw ()
{
    uno::Reference< report::XReportComponent> xReportComponent(xDescr,uno::UNO_QUERY);
    if ( xReportComponent.is() )
        return OObjectBase::createObject(xReportComponent);
    return SvxDrawPage::_CreateSdrObject( xDescr );
}

uno::Reference< drawing::XShape >  OReportDrawPage::_CreateShape( SdrObject *pObj ) const throw ()
{
    OObjectBase* pBaseObj = dynamic_cast<OObjectBase*>(pObj);
    if ( !pBaseObj )
        return SvxDrawPage::_CreateShape( pObj );

    uno::Reference< report::XSection> xSection = m_xSection;
    uno::Reference< lang::XMultiServiceFactory> xFactory;
    if ( xSection.is() )
        xFactory.set(xSection->getReportDefinition(),uno::UNO_QUERY);
    uno::Reference< drawing::XShape > xRet;
    uno::Reference< drawing::XShape > xShape;
    if ( xFactory.is() )
    {
        bool bChangeOrientation = false;
        ::rtl::OUString sServiceName = pBaseObj->getServiceName();
        OSL_ENSURE(sServiceName.getLength(),"No Service Name given!");

        if ( pObj->ISA(OUnoObject) )
        {
            OUnoObject* pUnoObj = dynamic_cast<OUnoObject*>(pObj);
            if ( pUnoObj->GetObjIdentifier() == OBJ_DLG_FIXEDTEXT )
            {
                uno::Reference<beans::XPropertySet> xControlModel(pUnoObj->GetUnoControlModel(),uno::UNO_QUERY);
                if ( xControlModel.is() )
                    xControlModel->setPropertyValue( PROPERTY_MULTILINE,uno::makeAny(sal_True));
            }
            else
                bChangeOrientation = pUnoObj->GetObjIdentifier() == OBJ_DLG_HFIXEDLINE;
            SvxShapeControl* pShape = new SvxShapeControl( pObj );
            xShape.set(static_cast<cppu::OWeakObject*>(static_cast<SvxShape_UnoImplHelper *>(pShape)),uno::UNO_QUERY);
            pShape->setShapeKind(pObj->GetObjIdentifier());
        }
        else if ( pObj->ISA(OCustomShape) )
        {
            SvxCustomShape* pShape = new SvxCustomShape( pObj );
            uno::Reference < drawing::XEnhancedCustomShapeDefaulter > xShape2 = pShape;
            xShape.set(xShape2,uno::UNO_QUERY);
            pShape->setShapeKind(pObj->GetObjIdentifier());
        }
        else if ( pObj->ISA(SdrOle2Obj) )
        {
            SdrOle2Obj* pOle2Obj = dynamic_cast<SdrOle2Obj*>(pObj);
            if ( !pOle2Obj->GetObjRef().is() )
            {
                sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
                uno::Reference < embed::XEmbeddedObject > xObj;
                ::rtl::OUString sName;
                xObj = pObj->GetModel()->GetPersist()->getEmbeddedObjectContainer().CreateEmbeddedObject(
                    ::comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation(
                    ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("80243D39-6741-46C5-926E-069164FF87BB"))), sName );
                OSL_ENSURE(xObj.is(),"Embedded Object could not be created!");

                /**************************************************
                * Das leere OLE-Objekt bekommt ein neues IPObj
                **************************************************/
                pObj->SetEmptyPresObj(sal_False);
                pOle2Obj->SetOutlinerParaObject(NULL);
                pOle2Obj->SetObjRef(xObj);
                pOle2Obj->SetPersistName(sName);
                pOle2Obj->SetName(sName);
                pOle2Obj->SetAspect(nAspect);
                Rectangle aRect = pOle2Obj->GetLogicRect();

                Size aTmp = aRect.GetSize();
                awt::Size aSz( aTmp.Width(), aTmp.Height() );
                xObj->setVisualAreaSize( nAspect, aSz );
            }
            SvxOle2Shape* pShape = new SvxOle2Shape( pObj );
            xShape.set(*pShape,uno::UNO_QUERY);
            pShape->setShapeKind(pObj->GetObjIdentifier());
        }

        if ( !xShape.is() )
            xShape.set( SvxDrawPage::_CreateShape( pObj ) );

        try
        {
            OReportModel* pRptModel = static_cast<OReportModel*>(pObj->GetModel());
            xRet.set( pRptModel->createShape(sServiceName,xShape,bChangeOrientation ? 0 : 1), uno::UNO_QUERY_THROW );
        }
        catch( const uno::Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    return xRet;
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
  This file is part of KOrganizer.

  Copyright (c) 1997, 1998 Preston Brown <pbrown@kde.org>
  Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
  Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>

  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 Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "kojournaleditor.h"
#include "koeditorgeneraljournal.h"
#include "koeditordetails.h"
#include "koeditorattachments.h"
#include "kodialogmanager.h"
#include "koprefs.h"
#include "korganizer/baseview.h"

#include <kcal/journal.h>
#include <kcal/calendarlocal.h>

#include <kmessagebox.h>
#include <klocale.h>

#include <QLayout>
#include <QVBoxLayout>
#include <QFrame>
#include <QBoxLayout>

using namespace KCal;

KOJournalEditor::KOJournalEditor( Calendar *calendar, QWidget *parent )
  : KOIncidenceEditor( i18n( "Edit Journal Entry" ), calendar, parent ),
    mJournal( 0 ), mCalendar( 0 )
{
}

KOJournalEditor::~KOJournalEditor()
{
  emit dialogClose( mJournal );
}

void KOJournalEditor::init()
{
  setupGeneral();
  setupAttendeesTab();
}

void KOJournalEditor::reload()
{
  if ( mJournal ) {
    readJournal( mJournal );
  }
}

void KOJournalEditor::setupGeneral()
{
  mGeneral = new KOEditorGeneralJournal( mCalendar, this );

  QFrame *topFrame = new QFrame();
  addPage( topFrame, i18nc( "@title general journal settings", "General" ) );

  QBoxLayout *topLayout = new QVBoxLayout( topFrame );
  if ( KOPrefs::instance()->mCompactDialogs ) {
    topLayout->setMargin( marginHint() );
  }
  topLayout->setSpacing( spacingHint() );

  mGeneral->initTitle( topFrame, topLayout );
  mGeneral->initDate( topFrame, topLayout );
  mGeneral->initDescription( topFrame, topLayout );
  mGeneral->initCategories( topFrame, topLayout );

  mGeneral->finishSetup();
}

void KOJournalEditor::editIncidence( Incidence *incidence, Calendar * )
{
  Journal *journal=dynamic_cast<Journal*>( incidence );
  if ( journal ) {
    init();

    mJournal = journal;
    readJournal( mJournal );
  }
}

void KOJournalEditor::newJournal()
{
  init();
  mJournal = 0;
  loadDefaults();
}

void KOJournalEditor::setTexts( const QString &summary,
                                const QString &description,
                                bool richDescription )
{
  if ( description.isEmpty() && summary.contains( "\n" ) ) {
    mGeneral->setDescription( summary, false );
    int pos = summary.indexOf( "\n" );
    mGeneral->setSummary( summary.left( pos ) );
  } else {
    mGeneral->setSummary( summary );
    mGeneral->setDescription( description, richDescription );
  }
}

void KOJournalEditor::loadDefaults()
{
  setDate( QDate::currentDate() );
  setTime( QTime::currentTime() );
}

bool KOJournalEditor::processInput()
{
  if ( !validateInput() ) {
    return false;
  }

  if ( mJournal ) {
    Journal *oldJournal = mJournal->clone();
    fillJournal( mJournal );
    mChanger->changeIncidence( oldJournal, mJournal );
    delete oldJournal;
  } else {
    mJournal = new Journal;
    mJournal->setOrganizer( Person( KOPrefs::instance()->fullName(),
                            KOPrefs::instance()->email() ) );

    fillJournal( mJournal );

    if ( !mChanger->addIncidence( mJournal, this ) ) {
      delete mJournal;
      mJournal = 0;
      return false;
    }
  }

  return true;
}

void KOJournalEditor::deleteJournal()
{
  if ( mJournal ) {
    emit deleteIncidenceSignal( mJournal );
  }

  emit dialogClose( mJournal );
  reject();
}

void KOJournalEditor::setDate( const QDate &date )
{
  mGeneral->setDate( date );
}

void KOJournalEditor::setTime( const QTime &time )
{
  mGeneral->setTime( time );
}

bool KOJournalEditor::incidenceModified() {
  Journal *newJournal = 0;

  if ( mJournal ) {
    newJournal = mJournal->clone();
    fillJournal( newJournal );
  }
  return mJournal && !( *newJournal == *mJournal );
}

void KOJournalEditor::readJournal( Journal *journal, bool tmpl )
{
  //TODO: just tmpl variable
  Q_UNUSED( tmpl );

  if ( !journal ) {
    return;
  }

  mGeneral->readJournal( journal );
  mDetails->readIncidence( journal );
}

void KOJournalEditor::fillJournal( Journal *journal )
{
  mGeneral->fillJournal( journal );
  mDetails->fillIncidence( journal );
}

bool KOJournalEditor::validateInput()
{
  return mGeneral->validateInput();
}

int KOJournalEditor::msgItemDelete()
{
  return KMessageBox::warningContinueCancel(
    this,
    i18n( "This journal entry will be permanently deleted." ),
    i18n( "KOrganizer Confirmation" ),
    KGuiItem( i18n( "Delete" ), "edit-delete" ) );
}

void KOJournalEditor::modified( int /*modification*/)
{
  // Play dump, just reload the Journal. This dialog has become so complicated that
  // there is no point in trying to be smart here...
  reload();
}

void KOJournalEditor::loadTemplate( CalendarLocal &cal )
{
  Journal::List journals = cal.journals();
  if ( journals.count() == 0 ) {
    KMessageBox::error( this, i18n( "Template does not contain a valid journal." ) );
  } else {
    readJournal( journals.first() );
  }
}

void KOJournalEditor::slotSaveTemplate( const QString &templateName )
{
  Journal *journal = new Journal;
  fillJournal( journal );
  saveAsTemplate( journal, templateName );
}

QStringList &KOJournalEditor::templates() const
{
  return KOPrefs::instance()->mJournalTemplates;
}

#include "kojournaleditor.moc"
<commit_msg>backport SVN commit 956252 by winterz:<commit_after>/*
  This file is part of KOrganizer.

  Copyright (c) 1997, 1998 Preston Brown <pbrown@kde.org>
  Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
  Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>

  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 Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "kojournaleditor.h"
#include "koeditorgeneraljournal.h"
#include "koeditordetails.h"
#include "koeditorattachments.h"
#include "kodialogmanager.h"
#include "koprefs.h"
#include "korganizer/baseview.h"

#include <kcal/journal.h>
#include <kcal/calendarlocal.h>

#include <kmessagebox.h>
#include <klocale.h>

#include <QLayout>
#include <QVBoxLayout>
#include <QFrame>
#include <QBoxLayout>

using namespace KCal;

KOJournalEditor::KOJournalEditor( Calendar *calendar, QWidget *parent )
  : KOIncidenceEditor( i18n( "Edit Journal Entry" ), calendar, parent ),
    mJournal( 0 ), mCalendar( 0 )
{
}

KOJournalEditor::~KOJournalEditor()
{
  emit dialogClose( mJournal );
}

void KOJournalEditor::init()
{
  setupGeneral();
  setupAttendeesTab();

  connect( mGeneral, SIGNAL(openCategoryDialog()),
           SIGNAL(editCategories()) );
  connect( this, SIGNAL(updateCategoryConfig()),
           mGeneral, SIGNAL(updateCategoryConfig()) );

  connect( mDetails, SIGNAL(updateAttendeeSummary(int)),
           mGeneral, SLOT(updateAttendeeSummary(int)) );
}

void KOJournalEditor::reload()
{
  if ( mJournal ) {
    readJournal( mJournal );
  }
}

void KOJournalEditor::setupGeneral()
{
  mGeneral = new KOEditorGeneralJournal( mCalendar, this );

  QFrame *topFrame = new QFrame();
  addPage( topFrame, i18nc( "@title general journal settings", "General" ) );

  QBoxLayout *topLayout = new QVBoxLayout( topFrame );
  if ( KOPrefs::instance()->mCompactDialogs ) {
    topLayout->setMargin( marginHint() );
  }
  topLayout->setSpacing( spacingHint() );

  mGeneral->initTitle( topFrame, topLayout );
  mGeneral->initDate( topFrame, topLayout );
  mGeneral->initDescription( topFrame, topLayout );
  mGeneral->initCategories( topFrame, topLayout );

  mGeneral->finishSetup();
}

void KOJournalEditor::editIncidence( Incidence *incidence, Calendar * )
{
  Journal *journal=dynamic_cast<Journal*>( incidence );
  if ( journal ) {
    init();

    mJournal = journal;
    readJournal( mJournal );
  }
}

void KOJournalEditor::newJournal()
{
  init();
  mJournal = 0;
  loadDefaults();
}

void KOJournalEditor::setTexts( const QString &summary,
                                const QString &description,
                                bool richDescription )
{
  if ( description.isEmpty() && summary.contains( "\n" ) ) {
    mGeneral->setDescription( summary, false );
    int pos = summary.indexOf( "\n" );
    mGeneral->setSummary( summary.left( pos ) );
  } else {
    mGeneral->setSummary( summary );
    mGeneral->setDescription( description, richDescription );
  }
}

void KOJournalEditor::loadDefaults()
{
  setDate( QDate::currentDate() );
  setTime( QTime::currentTime() );
}

bool KOJournalEditor::processInput()
{
  if ( !validateInput() ) {
    return false;
  }

  if ( mJournal ) {
    Journal *oldJournal = mJournal->clone();
    fillJournal( mJournal );
    mChanger->changeIncidence( oldJournal, mJournal );
    delete oldJournal;
  } else {
    mJournal = new Journal;
    mJournal->setOrganizer( Person( KOPrefs::instance()->fullName(),
                            KOPrefs::instance()->email() ) );

    fillJournal( mJournal );

    if ( !mChanger->addIncidence( mJournal, this ) ) {
      delete mJournal;
      mJournal = 0;
      return false;
    }
  }

  return true;
}

void KOJournalEditor::deleteJournal()
{
  if ( mJournal ) {
    emit deleteIncidenceSignal( mJournal );
  }

  emit dialogClose( mJournal );
  reject();
}

void KOJournalEditor::setDate( const QDate &date )
{
  mGeneral->setDate( date );
}

void KOJournalEditor::setTime( const QTime &time )
{
  mGeneral->setTime( time );
}

bool KOJournalEditor::incidenceModified() {
  Journal *newJournal = 0;

  if ( mJournal ) {
    newJournal = mJournal->clone();
    fillJournal( newJournal );
  }
  return mJournal && !( *newJournal == *mJournal );
}

void KOJournalEditor::readJournal( Journal *journal, bool tmpl )
{
  //TODO: just tmpl variable
  Q_UNUSED( tmpl );

  if ( !journal ) {
    return;
  }

  mGeneral->readJournal( journal );
  mDetails->readIncidence( journal );
}

void KOJournalEditor::fillJournal( Journal *journal )
{
  mGeneral->fillJournal( journal );
  mDetails->fillIncidence( journal );
}

bool KOJournalEditor::validateInput()
{
  return mGeneral->validateInput();
}

int KOJournalEditor::msgItemDelete()
{
  return KMessageBox::warningContinueCancel(
    this,
    i18n( "This journal entry will be permanently deleted." ),
    i18n( "KOrganizer Confirmation" ),
    KGuiItem( i18n( "Delete" ), "edit-delete" ) );
}

void KOJournalEditor::modified( int /*modification*/)
{
  // Play dump, just reload the Journal. This dialog has become so complicated that
  // there is no point in trying to be smart here...
  reload();
}

void KOJournalEditor::loadTemplate( CalendarLocal &cal )
{
  Journal::List journals = cal.journals();
  if ( journals.count() == 0 ) {
    KMessageBox::error( this, i18n( "Template does not contain a valid journal." ) );
  } else {
    readJournal( journals.first() );
  }
}

void KOJournalEditor::slotSaveTemplate( const QString &templateName )
{
  Journal *journal = new Journal;
  fillJournal( journal );
  saveAsTemplate( journal, templateName );
}

QStringList &KOJournalEditor::templates() const
{
  return KOPrefs::instance()->mJournalTemplates;
}

#include "kojournaleditor.moc"
<|endoftext|>