mirror of https://github.com/KLayout/klayout.git
WIP: create packages from templates
Now, packages are actually created.
This commit is contained in:
parent
4a90479187
commit
10b09c3575
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QResource>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
|
@ -215,8 +216,91 @@ Salt::remove_grain (const SaltGrain &grain)
|
|||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A helper class required because directory traversal is not supported by QResource directly
|
||||
* This class supports resource file trees and extraction of a tree from the latter
|
||||
*/
|
||||
class ResourceDir
|
||||
: public QResource
|
||||
{
|
||||
public:
|
||||
using QResource::isFile;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* Creates a resource representing a resource tree.
|
||||
*/
|
||||
ResourceDir (const QString &path)
|
||||
: QResource (path)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes the resource tree to the target directory
|
||||
* Returns false on error - see log in this case.
|
||||
*/
|
||||
bool copy_to (const QDir &target)
|
||||
{
|
||||
if (isDir ()) {
|
||||
|
||||
QStringList templ_dir = children ();
|
||||
for (QStringList::const_iterator t = templ_dir.begin (); t != templ_dir.end (); ++t) {
|
||||
|
||||
ResourceDir child_res (fileName () + QString::fromUtf8 ("/") + *t);
|
||||
if (child_res.isFile ()) {
|
||||
|
||||
QFile file (target.absoluteFilePath (*t));
|
||||
if (! file.open (QIODevice::WriteOnly)) {
|
||||
tl::error << QObject::tr ("Unable to open target file for writing: %1").arg (target.absoluteFilePath (*t));
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
if (child_res.isCompressed ()) {
|
||||
data = qUncompress ((const unsigned char *)child_res.data (), (int)child_res.size ());
|
||||
} else {
|
||||
data = QByteArray ((const char *)child_res.data (), (int)child_res.size ());
|
||||
}
|
||||
|
||||
file.write (data);
|
||||
|
||||
file.close ();
|
||||
|
||||
} else {
|
||||
|
||||
QFileInfo child_dir (target.absoluteFilePath (*t));
|
||||
if (! child_dir.exists ()) {
|
||||
if (! target.mkdir (*t)) {
|
||||
tl::error << QObject::tr ("Unable to create target directory: %1").arg (child_dir.path ());
|
||||
return false;
|
||||
}
|
||||
} else if (! child_dir.isDir ()) {
|
||||
tl::error << QObject::tr ("Unable to create target directory (is a file already): %1").arg (child_dir.path ());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! child_res.copy_to (QDir (target.absoluteFilePath (*t)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
Salt::create_grain (const SaltGrain &templ, SaltGrain &target, SaltDownloadManager &download_manager)
|
||||
Salt::create_grain (const SaltGrain &templ, SaltGrain &target, SaltDownloadManager *download_manager)
|
||||
{
|
||||
tl_assert (!m_root.is_empty ());
|
||||
|
||||
|
|
@ -243,15 +327,23 @@ Salt::create_grain (const SaltGrain &templ, SaltGrain &target, SaltDownloadManag
|
|||
// change down to the desired target location and create the directory structure while doing so
|
||||
std::vector<std::string> name_parts = tl::split (target.name (), "/");
|
||||
for (std::vector<std::string>::const_iterator n = name_parts.begin (); n != name_parts.end (); ++n) {
|
||||
QDir subdir (target_dir.filePath (tl::to_qstring (*n)));
|
||||
if (! subdir.exists ()) {
|
||||
|
||||
QFileInfo subdir (target_dir.filePath (tl::to_qstring (*n)));
|
||||
if (subdir.exists () && ! subdir.isDir ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Unable to create target directory '%1' for installing package - is already a file").arg (subdir.path ())));
|
||||
} else if (! subdir.exists ()) {
|
||||
if (! target_dir.mkdir (tl::to_qstring (*n))) {
|
||||
throw tl::Exception (tl::to_string (tr ("Unable to create target directory '%1' for installing package").arg (subdir.path ())));
|
||||
}
|
||||
if (! target_dir.cd (tl::to_qstring (*n))) {
|
||||
throw tl::Exception (tl::to_string (tr ("Unable to change to target directory '%1' for installing package").arg (subdir.path ())));
|
||||
}
|
||||
} else {
|
||||
if (! target_dir.cd (tl::to_qstring (*n))) {
|
||||
throw tl::Exception (tl::to_string (tr ("Unable to change to target directory '%1' for installing package").arg (subdir.path ())));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
|
|
@ -261,30 +353,46 @@ Salt::create_grain (const SaltGrain &templ, SaltGrain &target, SaltDownloadManag
|
|||
|
||||
bool res = true;
|
||||
|
||||
std::string target_name = target.name ();
|
||||
target = templ;
|
||||
target.set_path (tl::to_string (target_dir.absolutePath ()));
|
||||
target.set_name (target_name);
|
||||
|
||||
if (! templ.path ().empty ()) {
|
||||
|
||||
// if the template represents an actual folder, use the files from there
|
||||
tl::info << QObject::tr ("Copying package from '%1' to '%2' ..").arg (tl::to_qstring (templ.path ())).arg (tl::to_qstring (target.path ()));
|
||||
res = tl::cp_dir_recursive (templ.path (), target.path ());
|
||||
if (templ.path ()[0] != ':') {
|
||||
|
||||
// if the template represents an actual folder, use the files from there
|
||||
tl::info << QObject::tr ("Copying package from '%1' to '%2' ..").arg (tl::to_qstring (templ.path ())).arg (tl::to_qstring (target.path ()));
|
||||
res = tl::cp_dir_recursive (templ.path (), target.path ());
|
||||
|
||||
} else {
|
||||
|
||||
// if the template represents a resource path, use the files from there
|
||||
tl::info << QObject::tr ("Installing package from resource '%1' to '%2' ..").arg (tl::to_qstring (templ.path ())).arg (tl::to_qstring (target.path ()));
|
||||
res = ResourceDir (tl::to_qstring (templ.path ())).copy_to (QDir (tl::to_qstring (target.path ())));
|
||||
|
||||
}
|
||||
|
||||
} else if (! templ.url ().empty ()) {
|
||||
|
||||
tl_assert (download_manager != 0);
|
||||
|
||||
// otherwise download from the URL
|
||||
tl::info << QObject::tr ("Downloading package from '%1' to '%2' ..").arg (tl::to_qstring (templ.url ())).arg (tl::to_qstring (target.path ()));
|
||||
res = download_manager.download (templ.url (), target.path ());
|
||||
res = download_manager->download (templ.url (), target.path ());
|
||||
|
||||
}
|
||||
|
||||
if (res) {
|
||||
|
||||
tl::info << QObject::tr ("Package '%1' installed").arg (tl::to_qstring (target.name ()));
|
||||
|
||||
target.set_installed_time (QDateTime::currentDateTime ());
|
||||
target.save ();
|
||||
|
||||
// NOTE: this is a bit brute force .. we could as well try to insert the new grain into the existing structure
|
||||
refresh ();
|
||||
|
||||
} else {
|
||||
|
||||
tl::warn << QObject::tr ("Failed to install package '%1' - removing files ..").arg (tl::to_qstring (target.name ()));
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ public:
|
|||
*
|
||||
* Returns true, if the package could be created successfully.
|
||||
*/
|
||||
bool create_grain (const SaltGrain &templ, SaltGrain &target, SaltDownloadManager &download_manager);
|
||||
bool create_grain (const SaltGrain &templ, SaltGrain &target, SaltDownloadManager *download_manager = 0);
|
||||
|
||||
signals:
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ SaltGrain::valid_name (const std::string &n)
|
|||
|
||||
// this captures the cases where the extractor skips blanks
|
||||
// TODO: the extractor should have a "non-blank-skipping" mode
|
||||
return s == n;
|
||||
return res == n;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "laySalt.h"
|
||||
#include "ui_SaltGrainTemplateSelectionDialog.h"
|
||||
#include "tlString.h"
|
||||
#include "tlExceptions.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
|
|
@ -152,7 +153,7 @@ public:
|
|||
|
||||
void update ()
|
||||
{
|
||||
// @@@
|
||||
reset ();
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -230,8 +231,8 @@ class SaltGrainTemplateSelectionDialog
|
|||
: public QDialog, private Ui::SaltGrainTemplateSelectionDialog
|
||||
{
|
||||
public:
|
||||
SaltGrainTemplateSelectionDialog (QWidget *parent)
|
||||
: QDialog (parent)
|
||||
SaltGrainTemplateSelectionDialog (QWidget *parent, lay::Salt *salt)
|
||||
: QDialog (parent), mp_salt (salt)
|
||||
{
|
||||
Ui::SaltGrainTemplateSelectionDialog::setupUi (this);
|
||||
|
||||
|
|
@ -249,11 +250,14 @@ public:
|
|||
SaltGrain *g = model->grain_from_index (salt_view->currentIndex ());
|
||||
tl_assert (g != 0);
|
||||
|
||||
g->set_name (tl::to_string (name_edit->text ().simplified ()));
|
||||
|
||||
return *g;
|
||||
}
|
||||
|
||||
std::string name () const
|
||||
{
|
||||
return tl::to_string (name_edit->text ());
|
||||
}
|
||||
|
||||
void accept ()
|
||||
{
|
||||
name_alert->clear ();
|
||||
|
|
@ -263,12 +267,23 @@ public:
|
|||
} else if (! SaltGrain::valid_name (name)) {
|
||||
name_alert->error () << tr ("Name is not valid (must be composed of letters, digits or underscores.\nGroups and names need to be separated with slashes.");
|
||||
} else {
|
||||
|
||||
// check, if this name does not exist yet
|
||||
for (Salt::flat_iterator g = mp_salt->begin_flat (); g != mp_salt->end_flat (); ++g) {
|
||||
if ((*g)->name () == name) {
|
||||
name_alert->error () << tr ("A package with this name already exists");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QDialog::accept ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
lay::Salt m_salt_templates;
|
||||
lay::Salt *mp_salt;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
|
@ -310,11 +325,6 @@ SaltManagerDialog::SaltManagerDialog (QWidget *parent)
|
|||
|
||||
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 ()));
|
||||
|
|
@ -334,40 +344,41 @@ SaltManagerDialog::edit_properties ()
|
|||
}
|
||||
}
|
||||
|
||||
// @@@
|
||||
namespace
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A helper class required because directory traversal is not supported by QResource directly
|
||||
*/
|
||||
class OpenResource
|
||||
: public QResource
|
||||
{
|
||||
public:
|
||||
using QResource::isDir;
|
||||
using QResource::isFile;
|
||||
using QResource::children;
|
||||
|
||||
OpenResource (const QString &path)
|
||||
: QResource (path)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
// @@@
|
||||
|
||||
void
|
||||
SaltManagerDialog::create_grain ()
|
||||
{
|
||||
SaltGrainTemplateSelectionDialog temp_dialog (this);
|
||||
BEGIN_PROTECTED
|
||||
|
||||
SaltGrainTemplateSelectionDialog temp_dialog (this, mp_salt);
|
||||
if (temp_dialog.exec ()) {
|
||||
|
||||
// @@@
|
||||
SaltGrain target;
|
||||
target.set_name (temp_dialog.name ());
|
||||
|
||||
if (mp_salt->create_grain (temp_dialog.templ (), target)) {
|
||||
|
||||
// select the new one
|
||||
SaltModel *model = dynamic_cast <SaltModel *> (salt_view->model ());
|
||||
if (model) {
|
||||
for (int i = model->rowCount (QModelIndex ()); i > 0; ) {
|
||||
--i;
|
||||
QModelIndex index = model->index (i, 0, QModelIndex ());
|
||||
SaltGrain *g = model->grain_from_index (index);
|
||||
if (g && g->name () == target.name ()) {
|
||||
salt_view->setCurrentIndex (index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (tr ("Initialization of new package failed - see log window (File/Log Viewer) for details")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -399,11 +410,20 @@ SaltManagerDialog::salt_changed ()
|
|||
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 ();
|
||||
|
||||
// select the first grain
|
||||
if (model->rowCount (QModelIndex ()) > 0) {
|
||||
salt_view->setCurrentIndex (model->index (0, 0, QModelIndex ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
current_changed ();
|
||||
|
|
|
|||
|
|
@ -162,6 +162,13 @@ TEST (2)
|
|||
EXPECT_EQ (lay::SaltGrain::valid_version ("\t1 . 2.\n3"), true);
|
||||
EXPECT_EQ (lay::SaltGrain::valid_version ("x"), false);
|
||||
EXPECT_EQ (lay::SaltGrain::valid_version ("1.2x"), false);
|
||||
EXPECT_EQ (lay::SaltGrain::valid_name (""), false);
|
||||
EXPECT_EQ (lay::SaltGrain::valid_name ("x"), true);
|
||||
EXPECT_EQ (lay::SaltGrain::valid_name ("x1"), true);
|
||||
EXPECT_EQ (lay::SaltGrain::valid_name ("x1 "), false);
|
||||
EXPECT_EQ (lay::SaltGrain::valid_name ("x$1"), false);
|
||||
EXPECT_EQ (lay::SaltGrain::valid_name ("x/y"), true);
|
||||
EXPECT_EQ (lay::SaltGrain::valid_name ("x_y"), true);
|
||||
EXPECT_EQ (lay::SaltGrain::compare_versions ("", ""), 0);
|
||||
EXPECT_EQ (lay::SaltGrain::compare_versions ("1", "2"), -1);
|
||||
EXPECT_EQ (lay::SaltGrain::compare_versions ("1", ""), 1);
|
||||
|
|
@ -185,7 +192,6 @@ TEST (2)
|
|||
EXPECT_EQ (lay::SaltGrain::compare_versions ("991", "990"), 1);
|
||||
}
|
||||
|
||||
|
||||
TEST (3)
|
||||
{
|
||||
const QString grain_spec_file = QString::fromUtf8 ("grain.xml");
|
||||
|
|
|
|||
Loading…
Reference in New Issue