22 #include <QFileSystemWatcher>
23 #include <QGridLayout>
24 #include <QInputDialog>
25 #include <QMessageBox>
26 #include <QPushButton>
27 #include <QSpacerItem>
28 #include <QTextStream>
29 #include <QApplication>
31 #include <QRegularExpression>
33 #include <QJsonDocument>
34 #include <QJsonObject>
40 mSettingAutosave =
new SettingsItemCheckbox(
44 "eXpert Settings:Autosave",
45 "Specifies wheather HAL should autosave."
48 mSettingAutosaveInterval =
new SettingsItemSpinbox(
50 "advanced/autosave_interval",
52 "eXpert Settings:Autosave",
53 "Sets after how much time in seconds an autosave will occur."
56 mAutosaveEnabled = mSettingAutosave->value().toBool();
57 mAutosaveInterval = mSettingAutosaveInterval->value().toInt();
59 if (mAutosaveInterval < 30)
60 mAutosaveInterval = 30;
62 connect(mSettingAutosave, &SettingsItemCheckbox::boolChanged,
this, [
this](
bool value){
63 mAutosaveEnabled = value;
64 if (mTimer->isActive())
65 mTimer->start(mAutosaveInterval * 1000);
68 connect(mSettingAutosaveInterval, &SettingsItemSpinbox::intChanged,
this, [
this](
int value){
69 mAutosaveInterval = value;
70 if (mTimer->isActive())
71 mTimer->start(mAutosaveInterval * 1000);
86 bool FileManager::fileOpen()
const
91 void FileManager::autosave()
94 if (pm->
get_project_status() != ProjectManager::ProjectStatus::NONE && mAutosaveEnabled)
98 log_info(
"gui",
"Autosave deferred while python script is running...");
101 log_info(
"gui",
"saving a backup in case something goes wrong...");
102 if (!ProjectManager::instance()->serialize_project(
gNetlist,
true))
115 void FileManager::watchFile(
const QString& fileName)
117 if (fileName == mFileName)
122 if (!mFileName.isEmpty())
124 mFileWatcher->removePath(mFileName);
125 removeShadowDirectory();
138 mTimer->start(mAutosaveInterval * 1000);
140 mFileName = fileName;
141 mFileWatcher->addPath(mFileName);
143 updateRecentFiles(mFileName);
149 Q_EMIT projectSaved(projectDir,
file);
155 Q_EMIT projectOpened(projectDir,
file);
158 ProjectManager::instance()->set_project_status(ProjectManager::ProjectStatus::OPENED);
165 if (!info.
exists())
return NotExisting;
172 return InvalidExtension;
192 if (nl.
isEmpty())
return NetlistError;
200 if (!
QFileInfo(
QDir(pathname).absoluteFilePath(nl)).exists())
204 if (gl.
isEmpty())
return GatelibError;
212 if (!
QFileInfo(
QDir(pathname).absoluteFilePath(gl)).exists())
218 return OtherDirectory;
221 return UnknownDirectoryEntry;
229 return QString(
"seems to be a HAL project");
231 return QString(
"no HAL project file found in current directory");
233 return QString(
"entry is not a directory but a file");
235 return QString(
"directory does not exist");
236 case InvalidExtension:
237 return QString(
"HAL project directory must not have an extension");
239 return QString(
"HAL project file parse error");
241 return QString(
"cannot find HAL netlist");
243 return QString(
"cannot find HAL gate library");
244 case UnknownDirectoryEntry:
245 return QString(
"entry is neither directory nor file");
251 void FileManager::fileSuccessfullyLoaded(
QString file)
254 Q_EMIT fileOpened(
file);
255 ProjectManager::instance()->set_project_status(ProjectManager::ProjectStatus::OPENED);
258 void FileManager::removeShadowDirectory()
260 ProjectManager* pm = ProjectManager::instance();
261 if (pm->get_project_status() == ProjectManager::ProjectStatus::NONE)
return;
265 shDir.removeRecursively();
271 void FileManager::newProject()
282 QMessageBox::warning(qApp->activeWindow(),
"Aborted",
"Cannot create project <" + projdir +
">, no gate library selected");
288 QMessageBox::warning(qApp->activeWindow(),
"Aborted",
"Cannot create project <" + projdir +
">, cannot load gate library <" + gatelib +
">");
295 QMessageBox::warning(qApp->activeWindow(),
"Aborted",
"Error creating project directory <" + projdir +
">");
299 QDir projectDir(projdir);
306 gatelib = targetGateLib;
310 LogManager::get_instance()->set_file_name(lpath);
317 QMessageBox::warning(qApp->activeWindow(),
"Aborted",
"Failed to create <" + projdir +
"> with gate library <" + gatelib +
">");
324 projectSuccessfullyLoaded(projdir,netlistFilename);
328 void FileManager::importFile(
QString filename)
331 QString testProjectExists(filename);
333 if (directoryStatus(testProjectExists) == FileManager::ProjectDirectory)
338 msgBox.
setText(
"A hal project exists for the selected netlist.");
351 openProject(testProjectExists);
367 if (!
QFileInfo(projdir).suffix().isEmpty())
369 QMessageBox::warning(qApp->activeWindow(),
"Aborted",
"selected project directory name must not have suffix ." +
QFileInfo(projdir).suffix());
376 QMessageBox::warning(qApp->activeWindow(),
"Aborted",
"Error creating project directory <" + projdir +
377 ">\nYou might want to try a different name or location");
381 QDir projectDir(projdir);
382 QString netlistFilename = filename;
395 gatelib = targetGateLib;
399 LogManager::get_instance()->set_file_name(lpath);
401 if (deprecatedOpenFile(netlistFilename, gatelib))
415 log_info(
"gui",
"Project directory removed since import failed.");
417 log_warning(
"gui",
"Failed to remove project directory after failed import attempt");
424 void FileManager::moveShadowToProject(
const QDir& shDir)
const
429 QString targetPath(finfo.absoluteFilePath());
430 targetPath.replace(replaceToken,
"/");
435 moveShadowToProject(
QDir(finfo.absoluteFilePath()));
437 else if (finfo.isFile())
441 log_info(
"gui",
"File restored from autosave: {}.", targetPath.toStdString());
445 log_info(
"gui",
"Cannot move {} from autosave to project directory.", finfo.absoluteFilePath().toStdString());
450 void FileManager::openProject(
QString projPath)
460 "It seems that HAL crashed during your last session. Last autosave was on " +
464 moveShadowToProject(shDir);
469 ProjectJson projFile(
QDir(projPath).absoluteFilePath(
".project.json"));
479 displayErrorMessage(errorMsg);
486 projectSuccessfullyLoaded(projPath, filename);
490 LogManager::get_instance()->set_file_name(lpath);
495 QString logical_file_name = filename;
508 QString errorMsg(
"Unable to open file. File name is empty");
510 displayErrorMessage(errorMsg);
518 std::string error_message(
"Unable to open file" + filename.
toStdString());
519 log_error(
"gui",
"Unable to open file '{}'", error_message);
525 if (nlInfo.
suffix()==
"hal")
538 fileSuccessfullyLoaded(logical_file_name);
543 std::string error_message(
"Failed to create netlist from .hal file");
556 if (!gatelibraryPath.
isEmpty())
570 fileSuccessfullyLoaded(logical_file_name);
576 displayErrorMessage(
"Failed to open netlist\nwith user selected gate library\n"+gatelibraryPath);
597 fileSuccessfullyLoaded(logical_file_name);
606 log_info(
"gui",
"Searching for (other) compatible netlists.");
616 std::string error_message(
"Unable to find a compatible gate library. Deserialization failed!");
623 log_info(
"gui",
"One compatible gate library found.");
630 log_info(
"gui",
"{} compatible gate libraries found. User has to select one.",
netlists.size());
642 dialog.
setLabelText(
"The specified file can be processed with more than one gate library. Please select which library should be used:");
646 std::string selection = dialog.
textValue().toStdString();
650 if (
n->get_gate_library()->get_name() == selection)
664 fileSuccessfullyLoaded(logical_file_name);
668 void FileManager::closeFile()
674 Q_EMIT fileAboutToClose(mFileName);
679 mFileWatcher->removePath(mFileName);
683 removeShadowDirectory();
689 ProjectManager::instance()->set_project_status(ProjectManager::ProjectStatus::NONE);
694 void FileManager::handleFileChanged(
const QString& path)
696 Q_EMIT fileChanged(path);
699 void FileManager::handleDirectoryChanged(
const QString& path)
701 Q_EMIT fileDirectoryChanged(path);
704 void FileManager::updateRecentFiles(
const QString&
file)
const
709 for (
int i = 0; i < 14; ++i)
733 std::vector<std::filesystem::path>
files;
736 std::filesystem::path file_path(
string.toStdString());
738 for (
const auto& other :
files)
740 if (std::filesystem::equivalent(file_path, other))
758 void FileManager::displayErrorMessage(
QString error_message)
then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file
Copyright The Montserrat Project in Original or Modified may be sold by itself Original or Modified Versions of the Font Software may be redistributed and or sold with any provided that each copy contains the above copyright notice and this license These can be included either as stand alone text files
void handleOpenDocument(const QString &fileName)
Stores information about the currently opened netlist.
void loadFeature(FacExtensionInterface::Feature ft, const QString &extension=QString())
bool isCopyGatelibChecked() const
QString projectDirectory() const
QString gateLibraryPath() const
bool isMoveNetlistChecked() const
void registerNetlistCallbacks()
void unregisterNetlistCallbacks()
void debugHandleFileClosed()
void debugHandleFileOpened()
bool isCopyGatelibChecked() const
QString projectDirectory() const
QString gateLibraryPath() const
GuiPluginTable * mGuiPluginTable
std::filesystem::path get_default_filename(const std::string &extension=std::string()) const
std::filesystem::path get_shadow_dir() const
QString gateLibraryFilename() const
bool create_project_directory(const std::string &path)
bool serialize_project(Netlist *netlist, bool shadow=false)
std::unique_ptr< Netlist > & get_netlist()
ProjectStatus get_project_status() const
void restore_project_file_from_autosave()
std::string get_netlist_filename() const
bool open_project(const std::string &path="")
const ProjectDirectory & get_project_directory() const
bool remove_project_directory()
void set_project_directory(const std::string &path)
#define log_error(channel,...)
#define log_info(channel,...)
#define log_warning(channel,...)
GateLibrary * load(std::filesystem::path file_path, bool reload)
std::unique_ptr< Netlist > create_netlist(const GateLibrary *gate_library)
Create a new empty netlist using the specified gate library.
std::unique_ptr< Netlist > load_netlist(const std::filesystem::path &netlist_file, const std::filesystem::path &gate_library_file)
Create a netlist from the given file.
std::vector< std::unique_ptr< Netlist > > load_netlists(const std::filesystem::path &netlist_file)
Create a netlist from a given file for each matching pre-loaded gate library.
bool can_parse(const std::filesystem::path &file_name)
PythonContext * gPythonContext
ContentManager * gContentManager
PluginRelay * gPluginRelay
FileStatusManager * gFileStatusManager
NetlistRelay * gNetlistRelay
std::shared_ptr< Netlist > gNetlistOwner
This file contains various functions to create and load netlists.
message(VERBOSE "Qt5Widgets_LIBRARIES: ${Qt5Widgets_LIBRARIES}") elseif(NOT Qt5Widgets_FOUND) set(Missing_package "TRUE") if(APPLE AND CMAKE_HOST_APPLE) message(STATUS "To install qt5 on MacOS using homebrew run following command
QString toString(Qt::DateFormat format) const const
QString absoluteFilePath(const QString &fileName) const const
QString absolutePath() const const
QFileInfoList entryInfoList(QDir::Filters filters, QDir::SortFlags sort) const const
bool mkpath(const QString &dirPath) const const
bool rename(const QString &oldName, const QString &newName)
bool copy(const QString &newName)
bool exists() const const
QString fileName() const const
bool isFile() const const
QDateTime lastModified() const const
QString suffix() const const
void directoryChanged(const QString &path)
void fileChanged(const QString &path)
void addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
int columnCount() const const
int rowCount() const const
void setLabelText(const QString &text)
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
bool isObject() const const
QJsonObject object() const const
bool contains(const QString &key) const const
void append(const T &value)
void move(int from, int to)
void prepend(const T &value)
virtual int exec() override
void setIcon(QMessageBox::Icon)
void setInformativeText(const QString &text)
QMessageBox::StandardButton question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
void setWindowTitle(const QString &title)
void setText(const QString &text)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
void beginGroup(const QString &prefix)
int beginReadArray(const QString &prefix)
void beginWriteArray(const QString &prefix, int size)
void remove(const QString &key)
void setArrayIndex(int i)
void setValue(const QString &key, const QVariant &value)
QVariant value(const QString &key, const QVariant &defaultValue) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString left(int n) const const
QString & remove(int position, int n)
std::string toStdString() const const
int indexOf(QStringView str, int from) const const
QString toString() const const