mirror of https://github.com/KLayout/klayout.git
WIP: first steps towards package browser
This commit is contained in:
parent
695a5d3169
commit
b8238a85f9
|
|
@ -21,6 +21,9 @@
|
|||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -56,6 +59,9 @@
|
|||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Install Package</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
|
|
@ -76,7 +82,7 @@
|
|||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>20</height>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
|
|
@ -86,6 +92,9 @@
|
|||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Create New Package</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
|
|
@ -103,6 +112,9 @@
|
|||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Uninstall Package</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
|
|
@ -115,47 +127,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="layResources.qrc">
|
||||
<normaloff>:/new_folder.png</normaloff>:/new_folder.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton_5">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="layResources.qrc">
|
||||
<normaloff>:/rename.png</normaloff>:/rename.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
|
|
@ -178,15 +156,13 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
<widget class="QListView" name="salt_view">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionRectVisible">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
@ -214,23 +190,69 @@
|
|||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string><html><body><center>No packages are installed currently.<br><br>You can use:<br>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>218</width>
|
||||
<height>138</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><body><center>No packages are installed currently.<br><br>You can use:<br>
|
||||
</center>
|
||||
<table>
|
||||
<tr><td width="30"><a href=":import"><img src=":/import.png"></a></td><td>to import a package from an external source</td></tr>
|
||||
<tr><td><a href=":add"><img src=":/add.png"></a></td><td>to create a new package</td></tr>
|
||||
</table>
|
||||
</body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
@ -250,13 +272,25 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
|
|
@ -269,13 +303,37 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QToolButton" name="edit_button">
|
||||
<property name="toolTip">
|
||||
<string>Edit Package Details</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="layResources.qrc">
|
||||
<normaloff>:/edit.png</normaloff>:/edit.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTextBrowser" name="textBrowser"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionNewFolder">
|
||||
<property name="icon">
|
||||
|
|
@ -336,16 +394,31 @@
|
|||
</action>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>treeWidget</tabstop>
|
||||
<tabstop>salt_view</tabstop>
|
||||
<tabstop>toolButton_4</tabstop>
|
||||
<tabstop>toolButton_2</tabstop>
|
||||
<tabstop>toolButton_3</tabstop>
|
||||
<tabstop>toolButton</tabstop>
|
||||
<tabstop>toolButton_5</tabstop>
|
||||
<tabstop>textBrowser</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="layResources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>clicked(QAbstractButton*)</signal>
|
||||
<receiver>SaltManagerDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>635</x>
|
||||
<y>421</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>653</x>
|
||||
<y>432</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
|||
|
|
@ -21,15 +21,166 @@
|
|||
*/
|
||||
|
||||
#include "laySaltManagerDialog.h"
|
||||
#include "laySalt.h"
|
||||
#include "tlString.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QTextDocument>
|
||||
#include <QPainter>
|
||||
#include <QDir>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
} else {
|
||||
return QVariant ();
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex index (int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid ()) {
|
||||
return QModelIndex ();
|
||||
} else {
|
||||
return createIndex (row, column);
|
||||
}
|
||||
}
|
||||
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
lay::Salt *mp_salt;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
QTextDocument doc;
|
||||
doc.setHtml (optionV4.text);
|
||||
doc.setTextWidth (textWidth);
|
||||
return QSize (textWidth, doc.size ().height ());
|
||||
}
|
||||
};
|
||||
|
||||
// @@@
|
||||
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")));
|
||||
}
|
||||
}
|
||||
// @@@
|
||||
|
||||
SaltManagerDialog::SaltManagerDialog (QWidget *parent)
|
||||
: QDialog (parent)
|
||||
{
|
||||
Ui::SaltManagerDialog::setupUi (this);
|
||||
|
||||
salt = lay::Salt (); salt_initialized = false; // @@@
|
||||
make_salt (); // @@@
|
||||
salt_view->setModel (new SaltModel (this, &salt));
|
||||
salt_view->setItemDelegate (new SaltItemDelegate (this));
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1820,24 +1820,6 @@ MarkerBrowserPage::set_max_marker_count (size_t max_marker_count)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
escape_to_html (std::string &out, const std::string &in)
|
||||
{
|
||||
for (const char *cp = in.c_str (); *cp; ++cp) {
|
||||
if (*cp == '<') {
|
||||
out += "<";
|
||||
} else if (*cp == '>') {
|
||||
out += ">";
|
||||
} else if (*cp == '&') {
|
||||
out += "&";
|
||||
} else if (*cp == '\n') {
|
||||
out += "<br/>";
|
||||
} else {
|
||||
out += *cp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkerBrowserPage::enable_updates (bool f)
|
||||
{
|
||||
|
|
@ -1955,13 +1937,13 @@ MarkerBrowserPage::update_info_text ()
|
|||
|
||||
if (category && n_category == 1 && ! category->description ().empty ()) {
|
||||
info += "<p style=\"color:blue; font-weight: bold\">";
|
||||
escape_to_html (info, category->description ());
|
||||
tl::escape_to_html (info, category->description ());
|
||||
info += "</p>";
|
||||
}
|
||||
|
||||
if (! m_error_text.empty ()) {
|
||||
info += "<p style=\"color:red; font-weight: bold\">";
|
||||
escape_to_html (info, m_error_text);
|
||||
tl::escape_to_html (info, m_error_text);
|
||||
info += "</p>";
|
||||
}
|
||||
|
||||
|
|
@ -1978,7 +1960,7 @@ MarkerBrowserPage::update_info_text ()
|
|||
if (v->tag_id () != 0) {
|
||||
const rdb::Tag &tag = mp_database->tags ().tag (v->tag_id ());
|
||||
info += "<b>";
|
||||
escape_to_html (info, tag.name ());
|
||||
tl::escape_to_html (info, tag.name ());
|
||||
info += ":</br> ";
|
||||
}
|
||||
|
||||
|
|
@ -1989,7 +1971,7 @@ MarkerBrowserPage::update_info_text ()
|
|||
value_string = std::string (value_string.begin (), value_string.begin () + max_length) + "...";
|
||||
}
|
||||
|
||||
escape_to_html (info, value_string);
|
||||
tl::escape_to_html (info, value_string);
|
||||
|
||||
info += "<br/>";
|
||||
|
||||
|
|
|
|||
|
|
@ -413,6 +413,32 @@ tl::to_word_or_quoted_string (const std::string &s, const char *non_term)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
tl::escape_to_html (std::string &out, const std::string &in, bool replace_newlines)
|
||||
{
|
||||
for (const char *cp = in.c_str (); *cp; ++cp) {
|
||||
if (*cp == '<') {
|
||||
out += "<";
|
||||
} else if (*cp == '>') {
|
||||
out += ">";
|
||||
} else if (*cp == '&') {
|
||||
out += "&";
|
||||
} else if (replace_newlines && *cp == '\n') {
|
||||
out += "<br/>";
|
||||
} else {
|
||||
out += *cp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
tl::escaped_to_html (const std::string &in, bool replace_newlines)
|
||||
{
|
||||
std::string s;
|
||||
escape_to_html (s, in, replace_newlines);
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
tl::from_string (const std::string &s, const char * &result)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -326,6 +326,18 @@ TL_PUBLIC int edit_distance (const std::string &a, const std::string &b);
|
|||
*/
|
||||
TL_PUBLIC std::string to_word_or_quoted_string (const std::string &s, const char *non_term = "_.$");
|
||||
|
||||
/**
|
||||
* @brief Escapes HTML (or XML) characters from in and adds the result to out
|
||||
* If "replace_newlines" is true, "\n" will be replaced by "<br/>".
|
||||
*/
|
||||
TL_PUBLIC void escape_to_html (std::string &out, const std::string &in, bool replace_newlines = true);
|
||||
|
||||
/**
|
||||
* @brief Escapes HTML (or XML) characters from in and returns the resulting string
|
||||
* If "replace_newlines" is true, "\n" will be replaced by "<br/>".
|
||||
*/
|
||||
TL_PUBLIC std::string escaped_to_html (const std::string &in, bool replace_newlines = true);
|
||||
|
||||
/**
|
||||
* @brief Set the number of digits resolution for a micron display
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -423,3 +423,20 @@ TEST(10)
|
|||
EXPECT_EQ (unescape_string (escape_string ("'a\n\003")), "'a\n\003");
|
||||
}
|
||||
|
||||
TEST(11)
|
||||
{
|
||||
std::string s;
|
||||
tl::escape_to_html (s, "x");
|
||||
EXPECT_EQ (s, "x");
|
||||
tl::escape_to_html (s, "<&>");
|
||||
EXPECT_EQ (s, "x<&>");
|
||||
s = std::string ();
|
||||
tl::escape_to_html (s, "a\nb");
|
||||
EXPECT_EQ (s, "a<br/>b");
|
||||
s = std::string ();
|
||||
tl::escape_to_html (s, "a\nb", false);
|
||||
EXPECT_EQ (s, "a\nb");
|
||||
EXPECT_EQ (tl::escaped_to_html ("x<&>"), "x<&>");
|
||||
EXPECT_EQ (tl::escaped_to_html ("a\nb"), "a<br/>b");
|
||||
EXPECT_EQ (tl::escaped_to_html ("a\nb", false), "a\nb");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue