2017-03-12 23:26:04 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
KLayout Layout Viewer
|
|
|
|
|
Copyright (C) 2006-2017 Matthias Koefferlein
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "laySaltManagerDialog.h"
|
2017-03-18 00:22:45 +01:00
|
|
|
#include "laySalt.h"
|
|
|
|
|
#include "tlString.h"
|
|
|
|
|
|
|
|
|
|
#include <QAbstractItemModel>
|
|
|
|
|
#include <QAbstractTextDocumentLayout>
|
|
|
|
|
#include <QStyledItemDelegate>
|
|
|
|
|
#include <QTextDocument>
|
|
|
|
|
#include <QPainter>
|
|
|
|
|
#include <QDir>
|
2017-03-18 22:36:33 +01:00
|
|
|
#include <QTextStream>
|
|
|
|
|
#include <QBuffer>
|
2017-03-12 23:26:04 +01:00
|
|
|
|
|
|
|
|
namespace lay
|
|
|
|
|
{
|
|
|
|
|
|
2017-03-18 22:36:33 +01:00
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief A model representing the salt grains for a QListView
|
|
|
|
|
*/
|
2017-03-18 00:22:45 +01:00
|
|
|
class SaltModel
|
|
|
|
|
: public QAbstractItemModel
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
SaltModel (QObject *parent, lay::Salt *salt)
|
|
|
|
|
: QAbstractItemModel (parent), mp_salt (salt)
|
|
|
|
|
{
|
|
|
|
|
// .. nothing yet ..
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariant data (const QModelIndex &index, int role) const
|
|
|
|
|
{
|
|
|
|
|
if (role == Qt::DisplayRole) {
|
|
|
|
|
|
|
|
|
|
const lay::SaltGrain *g = mp_salt->begin_flat ()[index.row ()];
|
|
|
|
|
|
|
|
|
|
std::string text = "<html><body>";
|
|
|
|
|
text += "<h4>";
|
|
|
|
|
text += tl::escaped_to_html (g->name ());
|
|
|
|
|
if (!g->version ().empty ()) {
|
|
|
|
|
text += " ";
|
|
|
|
|
text += tl::escaped_to_html (g->version ());
|
|
|
|
|
}
|
|
|
|
|
if (!g->title ().empty ()) {
|
|
|
|
|
text += " - ";
|
|
|
|
|
text += tl::escaped_to_html (g->title ());
|
|
|
|
|
}
|
|
|
|
|
text += "</h4>";
|
|
|
|
|
if (!g->doc ().empty ()) {
|
|
|
|
|
text += "<p>";
|
|
|
|
|
text += tl::escaped_to_html (g->doc ());
|
|
|
|
|
text += "</p>";
|
|
|
|
|
}
|
|
|
|
|
text += "</body></html>";
|
|
|
|
|
|
|
|
|
|
return tl::to_qstring (text);
|
|
|
|
|
|
2017-03-18 22:36:33 +01:00
|
|
|
} else if (role == Qt::DecorationRole) {
|
|
|
|
|
|
2017-03-19 00:42:09 +01:00
|
|
|
const lay::SaltGrain *g = mp_salt->begin_flat ()[index.row ()];
|
|
|
|
|
if (g->icon ().isNull ()) {
|
|
|
|
|
return QIcon (":/salt_icon.png");
|
|
|
|
|
} else {
|
|
|
|
|
QPixmap px = QPixmap::fromImage (g->icon ());
|
|
|
|
|
if (px.width () == 64) {
|
|
|
|
|
return px;
|
|
|
|
|
} else {
|
|
|
|
|
return px.scaled (QSize (64, 64), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-03-18 22:36:33 +01:00
|
|
|
|
2017-03-18 00:22:45 +01:00
|
|
|
} else {
|
|
|
|
|
return QVariant ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QModelIndex index (int row, int column, const QModelIndex &parent) const
|
|
|
|
|
{
|
|
|
|
|
if (parent.isValid ()) {
|
|
|
|
|
return QModelIndex ();
|
|
|
|
|
} else {
|
2017-03-18 22:36:33 +01:00
|
|
|
return createIndex (row, column, mp_salt->begin_flat () [row]);
|
2017-03-18 00:22:45 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QModelIndex parent (const QModelIndex & /*index*/) const
|
|
|
|
|
{
|
|
|
|
|
return QModelIndex ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int columnCount(const QModelIndex & /*parent*/) const
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rowCount (const QModelIndex &parent) const
|
|
|
|
|
{
|
|
|
|
|
if (parent.isValid ()) {
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
return mp_salt->end_flat () - mp_salt->begin_flat ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 22:36:33 +01:00
|
|
|
SaltGrain *grain_from_index (const QModelIndex &index) const
|
|
|
|
|
{
|
|
|
|
|
if (index.isValid ()) {
|
|
|
|
|
return static_cast<SaltGrain *> (index.internalPointer ());
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void update ()
|
|
|
|
|
{
|
|
|
|
|
// @@@
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 00:22:45 +01:00
|
|
|
public:
|
|
|
|
|
lay::Salt *mp_salt;
|
|
|
|
|
};
|
|
|
|
|
|
2017-03-18 22:36:33 +01:00
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief A delegate displaying the summary of a grain
|
|
|
|
|
*/
|
2017-03-18 00:22:45 +01:00
|
|
|
class SaltItemDelegate
|
|
|
|
|
: public QStyledItemDelegate
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
SaltItemDelegate (QObject *parent)
|
|
|
|
|
: QStyledItemDelegate (parent)
|
|
|
|
|
{
|
|
|
|
|
// .. nothing yet ..
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
|
|
|
|
{
|
|
|
|
|
QStyleOptionViewItemV4 optionV4 = option;
|
|
|
|
|
initStyleOption (&optionV4, index);
|
|
|
|
|
|
|
|
|
|
QStyle *style = optionV4.widget ? optionV4.widget->style () : QApplication::style ();
|
|
|
|
|
|
|
|
|
|
QTextDocument doc;
|
|
|
|
|
doc.setHtml (optionV4.text);
|
|
|
|
|
|
|
|
|
|
optionV4.text = QString ();
|
|
|
|
|
style->drawControl (QStyle::CE_ItemViewItem, &optionV4, painter);
|
|
|
|
|
|
|
|
|
|
QAbstractTextDocumentLayout::PaintContext ctx;
|
|
|
|
|
|
|
|
|
|
if (optionV4.state & QStyle::State_Selected) {
|
|
|
|
|
ctx.palette.setColor (QPalette::Text, optionV4.palette.color (QPalette::Active, QPalette::HighlightedText));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QRect textRect = style->subElementRect (QStyle::SE_ItemViewItemText, &optionV4);
|
|
|
|
|
painter->save ();
|
|
|
|
|
painter->translate (textRect.topLeft ());
|
|
|
|
|
painter->setClipRect (textRect.translated (-textRect.topLeft ()));
|
|
|
|
|
doc.documentLayout()->draw (painter, ctx);
|
|
|
|
|
painter->restore ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QSize sizeHint (const QStyleOptionViewItem &option, const QModelIndex &index) const
|
|
|
|
|
{
|
|
|
|
|
const int textWidth = 500;
|
|
|
|
|
|
|
|
|
|
QStyleOptionViewItemV4 optionV4 = option;
|
|
|
|
|
initStyleOption (&optionV4, index);
|
|
|
|
|
|
2017-03-18 22:36:33 +01:00
|
|
|
const QListView *view = dynamic_cast<const QListView *> (optionV4.widget);
|
|
|
|
|
QSize icon_size (0, 0);
|
|
|
|
|
if (view) {
|
|
|
|
|
icon_size = view->iconSize ();
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 00:22:45 +01:00
|
|
|
QTextDocument doc;
|
|
|
|
|
doc.setHtml (optionV4.text);
|
|
|
|
|
doc.setTextWidth (textWidth);
|
2017-03-18 22:36:33 +01:00
|
|
|
return QSize (textWidth + icon_size.width () + 6, std::max (icon_size.height () + 12, int (doc.size ().height ())));
|
2017-03-18 00:22:45 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-03-18 22:36:33 +01:00
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
|
// SaltManager implementation
|
|
|
|
|
|
2017-03-18 00:22:45 +01:00
|
|
|
// @@@
|
|
|
|
|
lay::Salt salt;
|
|
|
|
|
static bool salt_initialized = false;
|
|
|
|
|
void make_salt ()
|
|
|
|
|
{
|
|
|
|
|
if (!salt_initialized) {
|
|
|
|
|
salt_initialized = true;
|
|
|
|
|
salt.add_location (tl::to_string (QDir::homePath () + QString::fromUtf8("/.klayout/salt")));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// @@@
|
|
|
|
|
|
2017-03-12 23:26:04 +01:00
|
|
|
SaltManagerDialog::SaltManagerDialog (QWidget *parent)
|
2017-03-18 22:36:33 +01:00
|
|
|
: QDialog (parent),
|
|
|
|
|
m_current_changed_enabled (true)
|
2017-03-12 23:26:04 +01:00
|
|
|
{
|
|
|
|
|
Ui::SaltManagerDialog::setupUi (this);
|
|
|
|
|
|
2017-03-18 22:36:33 +01:00
|
|
|
// @@@
|
|
|
|
|
salt = lay::Salt (); salt_initialized = false;
|
|
|
|
|
make_salt ();
|
|
|
|
|
mp_salt = &salt;
|
|
|
|
|
// @@@
|
|
|
|
|
|
|
|
|
|
SaltModel *model = new SaltModel (this, mp_salt);
|
|
|
|
|
salt_view->setModel (model);
|
2017-03-18 00:22:45 +01:00
|
|
|
salt_view->setItemDelegate (new SaltItemDelegate (this));
|
|
|
|
|
|
2017-03-18 22:36:33 +01:00
|
|
|
connect (mp_salt, SIGNAL (collections_changed ()), this, SLOT (salt_changed ()));
|
|
|
|
|
|
|
|
|
|
// select the first grain
|
|
|
|
|
if (model->rowCount (QModelIndex ()) > 0) {
|
|
|
|
|
salt_view->setCurrentIndex (model->index (0, 0, QModelIndex ()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
salt_changed ();
|
|
|
|
|
|
|
|
|
|
connect (salt_view->selectionModel (), SIGNAL (currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT (current_changed ()));
|
|
|
|
|
|
|
|
|
|
|
2017-03-12 23:26:04 +01:00
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 22:36:33 +01:00
|
|
|
void
|
|
|
|
|
SaltManagerDialog::salt_changed ()
|
|
|
|
|
{
|
|
|
|
|
SaltModel *model = dynamic_cast <SaltModel *> (salt_view->model ());
|
|
|
|
|
if (! model) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_current_changed_enabled = false;
|
|
|
|
|
model->update ();
|
|
|
|
|
m_current_changed_enabled = true;
|
|
|
|
|
|
|
|
|
|
if (mp_salt->is_empty ()) {
|
|
|
|
|
list_stack->setCurrentIndex (1);
|
|
|
|
|
details_frame->hide ();
|
|
|
|
|
} else {
|
|
|
|
|
list_stack->setCurrentIndex (0);
|
|
|
|
|
details_frame->show ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_changed ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
SaltManagerDialog::current_changed ()
|
|
|
|
|
{
|
|
|
|
|
SaltModel *model = dynamic_cast <SaltModel *> (salt_view->model ());
|
|
|
|
|
if (! model) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SaltGrain *g = model->grain_from_index (salt_view->currentIndex ());
|
|
|
|
|
details_text->set_grain (g);
|
|
|
|
|
if (!g) {
|
|
|
|
|
details_frame->setEnabled (false);
|
|
|
|
|
delete_button->setEnabled (false);
|
|
|
|
|
} else {
|
|
|
|
|
details_frame->setEnabled (true);
|
|
|
|
|
delete_button->setEnabled (true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-12 23:26:04 +01:00
|
|
|
}
|