Start: apply clang format

This commit is contained in:
wmayer
2023-09-03 11:27:47 +02:00
committed by wwmayer
parent 102a428745
commit 17bf44ec9a
21 changed files with 806 additions and 520 deletions

View File

@@ -27,13 +27,15 @@
#include <Base/PyObjectBase.h>
namespace Start {
class Module : public Py::ExtensionModule<Module>
namespace Start
{
class Module: public Py::ExtensionModule<Module>
{
public:
Module() : Py::ExtensionModule<Module>("Start")
Module()
: Py::ExtensionModule<Module>("Start")
{
initialize("This module is the Start module."); // register with Python
initialize("This module is the Start module.");// register with Python
}
private:
@@ -44,7 +46,7 @@ PyObject* initModule()
return Base::Interpreter().addModule(new Module);
}
} // namespace Start
}// namespace Start
/* Python entry */
PyMOD_INIT_FUNC(Start)

View File

@@ -28,14 +28,11 @@
// Exporting of App classes
#ifdef FC_OS_WIN32
# define START_SHOW_SKETCHER
# define START_USE_DRAFTING
#else // for Linux
# define START_USE_DRAFTING
#define START_SHOW_SKETCHER
#define START_USE_DRAFTING
#else// for Linux
#define START_USE_DRAFTING
#endif
#endif

View File

@@ -26,8 +26,8 @@
#include <Base/Interpreter.h>
#include <Base/PyObjectBase.h>
#include <Gui/Application.h>
#include <Gui/WidgetFactory.h>
#include <Gui/Language/Translator.h>
#include <Gui/WidgetFactory.h>
#include "DlgStartPreferencesImp.h"
#include "Workbench.h"
@@ -44,13 +44,15 @@ void loadStartResource()
Gui::Translator::instance()->refresh();
}
namespace StartGui {
class Module : public Py::ExtensionModule<Module>
namespace StartGui
{
class Module: public Py::ExtensionModule<Module>
{
public:
Module() : Py::ExtensionModule<Module>("StartGui")
Module()
: Py::ExtensionModule<Module>("StartGui")
{
initialize("This module is the StartGui module."); // register with Python
initialize("This module is the StartGui module.");// register with Python
}
private:
@@ -61,7 +63,7 @@ PyObject* initModule()
return Base::Interpreter().addModule(new Module);
}
} // namespace StartGui
}// namespace StartGui
/* Python entry */
@@ -76,7 +78,7 @@ PyMOD_INIT_FUNC(StartGui)
try {
Base::Interpreter().runString("import WebGui");
}
catch(const Base::Exception& e) {
catch (const Base::Exception& e) {
PyErr_SetString(PyExc_ImportError, e.what());
PyMOD_Return(nullptr);
}
@@ -97,14 +99,16 @@ PyMOD_INIT_FUNC(StartGui)
PyObject* mod = StartGui::initModule();
Base::Console().Log("Loading GUI of Start module... done\n");
// clang-format off
// register preferences pages
new Gui::PrefPageProducer<StartGui::DlgStartPreferencesImp> (QT_TRANSLATE_NOOP("QObject", "Start"));
new Gui::PrefPageProducer<StartGui::DlgStartPreferencesImp>(QT_TRANSLATE_NOOP("QObject", "Start"));
// clang-format on
// instantiating the commands
CreateStartCommands();
StartGui::Workbench::init();
// add resources and reloads the translators
// add resources and reloads the translators
loadStartResource();
PyMOD_Return(mod);
}

View File

@@ -33,15 +33,15 @@ using namespace std;
DEF_STD_CMD(CmdStartPage)
CmdStartPage::CmdStartPage()
:Command("Start_StartPage")
: Command("Start_StartPage")
{
sAppModule = "Start";
sGroup = QT_TR_NOOP("Start");
sMenuText = QT_TR_NOOP("Start Page");
sToolTipText = QT_TR_NOOP("Displays the start page in a browser view");
sWhatsThis = "Start_StartPage";
sStatusTip = sToolTipText;
sPixmap = "StartWorkbench";
sAppModule = "Start";
sGroup = QT_TR_NOOP("Start");
sMenuText = QT_TR_NOOP("Start Page");
sToolTipText = QT_TR_NOOP("Displays the start page in a browser view");
sWhatsThis = "Start_StartPage";
sStatusTip = sToolTipText;
sPixmap = "StartWorkbench";
}
void CmdStartPage::activated(int iMsg)
@@ -53,7 +53,7 @@ void CmdStartPage::activated(int iMsg)
void CreateStartCommands()
{
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager();
rcCmdMgr.addCommand(new CmdStartPage());
}
}

View File

@@ -33,9 +33,9 @@ using namespace StartGui;
/**
* Constructs a DlgStartPreferencesImp which is a child of 'parent'
*/
DlgStartPreferencesImp::DlgStartPreferencesImp( QWidget* parent )
: PreferencePage( parent )
, ui(new Ui_DlgStartPreferences)
DlgStartPreferencesImp::DlgStartPreferencesImp(QWidget* parent)
: PreferencePage(parent)
, ui(new Ui_DlgStartPreferences)
{
ui->setupUi(this);
@@ -55,26 +55,26 @@ DlgStartPreferencesImp::DlgStartPreferencesImp( QWidget* parent )
menuText[text] = it;
}
{ // add special workbench to selection
QPixmap px = Gui::Application::Instance->workbenchIcon(QString::fromLatin1("NoneWorkbench"));
QString key = QString::fromLatin1("<last>");
QString value = QString::fromLatin1("$LastModule");
if (px.isNull()) {
ui->AutoloadModuleCombo->addItem(key, QVariant(value));
}
else {
ui->AutoloadModuleCombo->addItem(px, key, QVariant(value));
}
// add special workbench to selection
QPixmap px = Gui::Application::Instance->workbenchIcon(QString::fromLatin1("NoneWorkbench"));
QString key = QString::fromLatin1("<last>");
QString value = QString::fromLatin1("$LastModule");
if (px.isNull()) {
ui->AutoloadModuleCombo->addItem(key, QVariant(value));
}
else {
ui->AutoloadModuleCombo->addItem(px, key, QVariant(value));
}
for (QMap<QString, QString>::Iterator it = menuText.begin(); it != menuText.end(); ++it) {
QPixmap px = Gui::Application::Instance->workbenchIcon(it.value());
if (px.isNull())
if (px.isNull()) {
ui->AutoloadModuleCombo->addItem(it.key(), QVariant(it.value()));
else
}
else {
ui->AutoloadModuleCombo->addItem(px, it.key(), QVariant(it.value()));
}
}
}
/**
@@ -87,8 +87,9 @@ void DlgStartPreferencesImp::saveSettings()
int index = ui->AutoloadModuleCombo->currentIndex();
QVariant data = ui->AutoloadModuleCombo->itemData(index);
QString startWbName = data.toString();
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Start")->
SetASCII("AutoloadModule", startWbName.toLatin1());
App::GetApplication()
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Start")
->SetASCII("AutoloadModule", startWbName.toLatin1());
ui->colorButton_1->onSave();
ui->colorButton_2->onSave();
ui->colorButton_3->onSave();
@@ -118,8 +119,9 @@ void DlgStartPreferencesImp::saveSettings()
void DlgStartPreferencesImp::loadSettings()
{
std::string start = App::Application::Config()["StartWorkbench"];
start = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Start")->
GetASCII("AutoloadModule", start.c_str());
start = App::GetApplication()
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Start")
->GetASCII("AutoloadModule", start.c_str());
QString startWbName = QLatin1String(start.c_str());
ui->AutoloadModuleCombo->setCurrentIndex(ui->AutoloadModuleCombo->findData(startWbName));
ui->colorButton_1->onRestore();
@@ -151,7 +153,7 @@ void DlgStartPreferencesImp::loadSettings()
/**
* Sets the strings of the subwidgets using the current language.
*/
void DlgStartPreferencesImp::changeEvent(QEvent *ev)
void DlgStartPreferencesImp::changeEvent(QEvent* ev)
{
if (ev->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);

View File

@@ -23,29 +23,30 @@
#ifndef STARTGUI_DLGSTARTPREFERENCESIMP_H
#define STARTGUI_DLGSTARTPREFERENCESIMP_H
#include <memory>
#include <Gui/PropertyPage.h>
#include <memory>
class Ui_DlgStartPreferences;
namespace StartGui {
class DlgStartPreferencesImp : public Gui::Dialog::PreferencePage
{
Q_OBJECT
namespace StartGui
{
class DlgStartPreferencesImp: public Gui::Dialog::PreferencePage
{
Q_OBJECT
public:
explicit DlgStartPreferencesImp( QWidget* parent = nullptr );
~DlgStartPreferencesImp() override;
public:
explicit DlgStartPreferencesImp(QWidget* parent = nullptr);
~DlgStartPreferencesImp() override;
protected:
void saveSettings() override;
void loadSettings() override;
void changeEvent(QEvent *e) override;
protected:
void saveSettings() override;
void loadSettings() override;
void changeEvent(QEvent* e) override;
private:
std::unique_ptr<Ui_DlgStartPreferences> ui;
};
private:
std::unique_ptr<Ui_DlgStartPreferences> ui;
};
} // namespace StartGui
}// namespace StartGui
#endif // STARTGUI_DLGSTARTPREFERENCESIMP_H
#endif// STARTGUI_DLGSTARTPREFERENCESIMP_H

View File

@@ -30,6 +30,6 @@
// Qt Toolkit
#include <QCoreApplication>
#endif //_PreComp_
#endif//_PreComp_
#endif // STARTGUI_PRECOMPILED_H
#endif// STARTGUI_PRECOMPILED_H

View File

@@ -22,7 +22,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QCoreApplication>
#include <QCoreApplication>
#endif
#include <Base/Console.h>
@@ -31,8 +31,8 @@
#include <Base/Tools.h>
#include <Gui/Command.h>
#include <Gui/DockWindowManager.h>
#include <Gui/MainWindow.h>
#include <Gui/MDIView.h>
#include <Gui/MainWindow.h>
#include <Gui/ToolBarManager.h>
#include "Workbench.h"
@@ -81,23 +81,28 @@ void StartGui::Workbench::loadStartPage()
<< " def __init__(self):\n"
<< " self.browser=WebGui.openBrowserWindow(u\"" << escapedstr.c_str() << "\")\n"
#if defined(FC_OS_WIN32)
<< " self.browser.setHtml(StartPage.handle(), App.getResourceDir() + 'Mod/Start/StartPage/')\n"
<< " self.browser.setHtml(StartPage.handle(), App.getResourceDir() + "
"'Mod/Start/StartPage/')\n"
#else
<< " self.browser.setHtml(StartPage.handle(), 'file://' + App.getResourceDir() + 'Mod/Start/StartPage/')\n"
<< " self.browser.setHtml(StartPage.handle(), 'file://' + App.getResourceDir() "
"+ 'Mod/Start/StartPage/')\n"
#endif
<< " def onChange(self, par, reason):\n"
<< " try:\n"
<< " if reason == 'RecentFiles':\n"
#if defined(FC_OS_WIN32)
<< " self.browser.setHtml(StartPage.handle(), App.getResourceDir() + 'Mod/Start/StartPage/')\n\n"
<< " self.browser.setHtml(StartPage.handle(), App.getResourceDir() + "
"'Mod/Start/StartPage/')\n\n"
#else
<< " self.browser.setHtml(StartPage.handle(), 'file://' + App.getResourceDir() + 'Mod/Start/StartPage/')\n\n"
<< " self.browser.setHtml(StartPage.handle(), 'file://' + "
"App.getResourceDir() + 'Mod/Start/StartPage/')\n\n"
#endif
<< " except RuntimeError as e:\n"
<< " pass\n"
<< "class WebView(object):\n"
<< " def __init__(self):\n"
<< " self.pargrp = FreeCAD.ParamGet('User parameter:BaseApp/Preferences/RecentFiles')\n"
<< " self.pargrp = FreeCAD.ParamGet('User "
"parameter:BaseApp/Preferences/RecentFiles')\n"
<< " self.webPage = WebPage()\n"
<< " self.pargrp.Attach(self.webPage)\n"
<< " def __del__(self):\n"
@@ -143,7 +148,6 @@ Gui::ToolBarItem* StartGui::Workbench::setupToolBars() const
<< "Web_BrowserZoomOut";
return root;
}
Gui::ToolBarItem* StartGui::Workbench::setupCommandBars() const
@@ -155,7 +159,7 @@ Gui::ToolBarItem* StartGui::Workbench::setupCommandBars() const
Gui::DockWindowItems* StartGui::Workbench::setupDockWindows() const
{
Gui::DockWindowItems* root = Gui::StdWorkbench::setupDockWindows();
root->setVisibility(false); // hide all dock windows by default
root->setVisibility("Std_ComboView",true); // except of the combo view
root->setVisibility(false); // hide all dock windows by default
root->setVisibility("Std_ComboView", true);// except of the combo view
return root;
}

View File

@@ -26,12 +26,13 @@
#include <Gui/Workbench.h>
namespace StartGui {
namespace StartGui
{
/**
* @author Werner Mayer
*/
class Workbench : public Gui::StdWorkbench
class Workbench: public Gui::StdWorkbench
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -40,7 +41,7 @@ public:
~Workbench() override;
/** Defines the standard context menu. */
void setupContextMenu(const char* recipient,Gui::MenuItem*) const override;
void setupContextMenu(const char* recipient, Gui::MenuItem*) const override;
/** Run some actions when the workbench gets activated. */
void activated() override;
@@ -56,7 +57,7 @@ protected:
/** Returns a DockWindowItems structure of dock windows this workbench. */
Gui::DockWindowItems* setupDockWindows() const override;
}; // namespace StartGui
};// namespace StartGui
}
#endif // START_WORKBENCH_H
}// namespace StartGui
#endif// START_WORKBENCH_H

View File

@@ -1,24 +1,24 @@
#***************************************************************************
#* Copyright (c) 2001,2002 Juergen Riegel <juergen.riegel@web.de> *
#* *
#* This file is part of the FreeCAD CAx development system. *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* FreeCAD 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 for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with FreeCAD; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************/
# ***************************************************************************
# * Copyright (c) 2001,2002 Juergen Riegel <juergen.riegel@web.de> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * FreeCAD 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 for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with FreeCAD; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************/
# FreeCAD init script of the Start module

View File

@@ -1,25 +1,25 @@
#***************************************************************************
#* Copyright (c) 2002,2003 Juergen Riegel <juergen.riegel@web.de> *
#* *
#* This file is part of the FreeCAD CAx development system. *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* FreeCAD 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 for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with FreeCAD; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************/
# ***************************************************************************
# * Copyright (c) 2002,2003 Juergen Riegel <juergen.riegel@web.de> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * FreeCAD 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 for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with FreeCAD; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************/
# Start gui init module
#
@@ -27,10 +27,14 @@
# This is the second one of three init scripts, the third one
# runs when the gui is up
class StartWorkbench ( Workbench ):
class StartWorkbench(Workbench):
"Start workbench object"
def __init__(self):
self.__class__.Icon = FreeCAD.getResourceDir() + "Mod/Start/Resources/icons/StartWorkbench.svg"
self.__class__.Icon = (
FreeCAD.getResourceDir() + "Mod/Start/Resources/icons/StartWorkbench.svg"
)
self.__class__.MenuText = "Start"
self.__class__.ToolTip = "Start workbench"
@@ -42,6 +46,7 @@ class StartWorkbench ( Workbench ):
def GetClassName(self):
return "StartGui::Workbench"
Gui.addWorkbench(StartWorkbench())
FreeCAD.__unit_test__ += [ "TestStartGui" ]
FreeCAD.__unit_test__ += ["TestStartGui"]

View File

@@ -29,19 +29,19 @@
// Start
#ifndef StartExport
#ifdef Start_EXPORTS
# define StartExport FREECAD_DECL_EXPORT
#define StartExport FREECAD_DECL_EXPORT
#else
# define StartExport FREECAD_DECL_IMPORT
#define StartExport FREECAD_DECL_IMPORT
#endif
#endif
// StartGui
#ifndef StartGuiExport
#ifdef StartGui_EXPORTS
# define StartGuiExport FREECAD_DECL_EXPORT
#define StartGuiExport FREECAD_DECL_EXPORT
#else
# define StartGuiExport FREECAD_DECL_IMPORT
#define StartGuiExport FREECAD_DECL_IMPORT
#endif
#endif
#endif //START_GLOBAL_H
#endif// START_GLOBAL_H

View File

@@ -1,24 +1,25 @@
#***************************************************************************
#* Copyright (c) 2012 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * Copyright (c) 2012 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
rf = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start")
rf.SetBool("AllowDownload", True)

View File

@@ -41,13 +41,23 @@ if cfolders:
mod = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetString(
"DefaultImport" + ext, ""
)
if (
ext.lower() in ("fcstd", "stp", "step", "iges", "igs")
):
if ext.lower() in ("fcstd", "stp", "step", "iges", "igs"):
FreeCAD.loadFile(os.path.join(cfolder, f), mod)
elif (
ext.lower() in ("bmp", "cur", "gif", "ico", "pbm", "pgm", "png", "jpg",
"jpeg", "ppm", "svg", "svgz", "xbm", "xpm")
elif ext.lower() in (
"bmp",
"cur",
"gif",
"ico",
"pbm",
"pgm",
"png",
"jpg",
"jpeg",
"ppm",
"svg",
"svgz",
"xbm",
"xpm",
):
FreeCAD.newDocument()
FreeCADGui.insert(os.path.join(cfolder, f), FreeCAD.activeDocument().Name)
@@ -57,4 +67,5 @@ if cfolders:
FreeCADGui.activeDocument().sendMsgToViews("ViewFit")
from StartPage import StartPage
StartPage.postStart()

View File

@@ -1,23 +1,23 @@
#***************************************************************************
#* Copyright (c) 2016 Bernd Hahnebach <bernd@bimstatik.org> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * Copyright (c) 2016 Bernd Hahnebach <bernd@bimstatik.org> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import os
import FreeCAD
@@ -28,4 +28,5 @@ FreeCAD.loadFile(os.path.join(FreeCAD.getResourceDir() + "examples", filename))
FreeCADGui.activeDocument().sendMsgToViews("ViewFit")
from StartPage import StartPage
StartPage.postStart()

View File

@@ -1,23 +1,23 @@
#***************************************************************************
#* Copyright (c) 2018 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * Copyright (c) 2018 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import os
import FreeCAD
@@ -25,18 +25,28 @@ import FreeCADGui
# MRU will be given before this script is run
rf = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/RecentFiles")
filename = rf.GetString("MRU"+str(MRU))
filename = rf.GetString("MRU" + str(MRU))
ext = os.path.splitext(filename)[1].lower().strip(".")
mod = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetString(
"DefaultImport"+ext, ""
"DefaultImport" + ext, ""
)
if (
ext.lower() in ("fcstd", "stp", "step", "iges", "igs")
):
if ext.lower() in ("fcstd", "stp", "step", "iges", "igs"):
FreeCAD.loadFile(filename, mod)
elif (
ext.lower() in ("bmp", "cur", "gif", "ico", "pbm", "pgm", "png", "jpg",
"jpeg", "ppm", "svg", "svgz", "xbm", "xpm")
elif ext.lower() in (
"bmp",
"cur",
"gif",
"ico",
"pbm",
"pgm",
"png",
"jpg",
"jpeg",
"ppm",
"svg",
"svgz",
"xbm",
"xpm",
):
FreeCAD.newDocument()
FreeCADGui.insert(filename, FreeCAD.activeDocument().Name)
@@ -46,4 +56,5 @@ else:
FreeCADGui.activeDocument().sendMsgToViews("ViewFit")
from StartPage import StartPage
StartPage.postStart()

View File

@@ -27,14 +27,14 @@ from StartPage import StartPage
template_name = str(template)
if template_name == "empty_file":
FreeCADGui.runCommand('Std_New')
FreeCADGui.runCommand("Std_New")
StartPage.postStart()
elif template_name == "import_file":
FreeCADGui.runCommand('Std_New')
FreeCADGui.runCommand("Std_New")
StartPage.postStart()
FreeCADGui.runCommand("Std_Import")
elif template_name == "parametric_part":
FreeCADGui.runCommand('Std_New')
FreeCADGui.runCommand("Std_New")
FreeCADGui.activateWorkbench("PartDesignWorkbench")
FreeCADGui.runCommand("PartDesign_Body")
StartPage.postStart(False)
@@ -43,12 +43,12 @@ elif template_name == "parametric_part":
# FreeCADGui.activateWorkbench("PartWorkbench")
# StartPage.postStart(False)
elif template_name == "2d_draft":
FreeCADGui.runCommand('Std_New')
FreeCADGui.runCommand("Std_New")
FreeCADGui.activateWorkbench("DraftWorkbench")
FreeCADGui.runCommand("Std_ViewTop")
StartPage.postStart(False)
elif template_name == "architecture":
FreeCADGui.runCommand('Std_New')
FreeCADGui.runCommand("Std_New")
try:
import BimCommands
except Exception:

View File

@@ -1,23 +1,24 @@
#***************************************************************************
#* Copyright (c) 2020 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * Copyright (c) 2020 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCADGui
FreeCADGui.showPreferences("Start")

View File

@@ -1,23 +1,23 @@
#***************************************************************************
#* Copyright (c) 2018 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * Copyright (c) 2018 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
# This is the start page template. It builds an HTML global variable that
@@ -38,6 +38,7 @@ from PySide import QtCore, QtGui
try:
from addonmanager_macro import Macro as AM_Macro
has_am_macro = True
except ImportError:
has_am_macro = False
@@ -47,8 +48,8 @@ FreeCADGui.addLanguagePath(":/translations")
FreeCADGui.updateLocale()
iconprovider = QtGui.QFileIconProvider()
iconbank = {} # store pre-existing icons so we don't overpollute temp dir
tempfolder = None # store icons inside a subfolder in temp dir
iconbank = {} # store pre-existing icons so we don't overpollute temp dir
tempfolder = None # store icons inside a subfolder in temp dir
defaulticon = None # store a default icon for problematic file types
@@ -56,11 +57,10 @@ def gethexcolor(color):
"returns a color hex value #000000"
r = str(hex(int(((color>>24)&0xFF))))[2:].zfill(2)
g = str(hex(int(((color>>16)&0xFF))))[2:].zfill(2)
b = str(hex(int(((color>>8)&0xFF))))[2:].zfill(2)
return "#"+r+g+b
r = str(hex(int(((color >> 24) & 0xFF))))[2:].zfill(2)
g = str(hex(int(((color >> 16) & 0xFF))))[2:].zfill(2)
b = str(hex(int(((color >> 8) & 0xFF))))[2:].zfill(2)
return "#" + r + g + b
def isOpenableByFreeCAD(filename):
@@ -81,25 +81,26 @@ def isOpenableByFreeCAD(filename):
return False
def getInfo(filename):
"returns available file information"
global iconbank,tempfolder
global iconbank, tempfolder
tformat = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetString("TimeFormat","%m/%d/%Y %H:%M:%S")
tformat = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetString(
"TimeFormat", "%m/%d/%Y %H:%M:%S"
)
def getLocalTime(timestamp):
"returns a local time from a timestamp"
return time.strftime(tformat,time.localtime(timestamp))
return time.strftime(tformat, time.localtime(timestamp))
def getSize(size):
"returns a human-readable size"
if size > 1024*1024:
hsize = str(int(size/(1024*1024))) + "Mb"
if size > 1024 * 1024:
hsize = str(int(size / (1024 * 1024))) + "Mb"
elif size > 1024:
hsize = str(int(size/1024)) + "Kb"
hsize = str(int(size / 1024)) + "Kb"
else:
hsize = str(int(size)) + "b"
return hsize
@@ -114,8 +115,11 @@ def getInfo(filename):
except Exception:
# alternative method
import hashlib
fhash = hashlib.md5(bytes(urllib.parse.quote("file://"+path,safe=":/"),"ascii")).hexdigest()
thumb = os.path.join(os.path.expanduser("~"),".thumbnails","normal",fhash+".png")
fhash = hashlib.md5(
bytes(urllib.parse.quote("file://" + path, safe=":/"), "ascii")
).hexdigest()
thumb = os.path.join(os.path.expanduser("~"), ".thumbnails", "normal", fhash + ".png")
else:
uri = gnomevfs.get_uri_from_local_path(path)
thumb = gnome.ui.thumbnail_path_for_uri(uri, "normal")
@@ -123,7 +127,6 @@ def getInfo(filename):
return thumb
return None
if os.path.exists(filename):
if os.path.isdir(filename):
@@ -143,41 +146,45 @@ def getInfo(filename):
# get additional info from fcstd files
if filename.lower().endswith(".fcstd"):
try:
zfile=zipfile.ZipFile(filename)
zfile = zipfile.ZipFile(filename)
except Exception:
print("Cannot read file: ",filename)
print("Cannot read file: ", filename)
return None
files=zfile.namelist()
files = zfile.namelist()
# check for meta-file if it's really a FreeCAD document
if files[0] == "Document.xml":
try:
doc = zfile.read(files[0]).decode('utf-8')
doc = zfile.read(files[0]).decode("utf-8")
except OSError as e:
print ("Fail to load corrupted FCStd file: '{0}' with this error: {1}".format(filename, str(e)))
print(
"Fail to load corrupted FCStd file: '{0}' with this error: {1}".format(
filename, str(e)
)
)
return None
doc = doc.replace("\n"," ")
r = re.findall("Property name=\"CreatedBy.*?String value=\"(.*?)\"/>",doc)
doc = doc.replace("\n", " ")
r = re.findall('Property name="CreatedBy.*?String value="(.*?)"/>', doc)
if r:
author = r[0]
# remove email if present in author field
if "&lt;" in author:
author = author.split("&lt;")[0].strip()
r = re.findall("Property name=\"Company.*?String value=\"(.*?)\"/>",doc)
r = re.findall('Property name="Company.*?String value="(.*?)"/>', doc)
if r:
company = r[0]
r = re.findall("Property name=\"License.*?String value=\"(.*?)\"/>",doc)
r = re.findall('Property name="License.*?String value="(.*?)"/>', doc)
if r:
lic = r[0]
r = re.findall("Property name=\"Comment.*?String value=\"(.*?)\"/>",doc)
r = re.findall('Property name="Comment.*?String value="(.*?)"/>', doc)
if r:
descr = r[0]
if "thumbnails/Thumbnail.png" in files:
if filename in iconbank:
image = iconbank[filename]
else:
imagedata=zfile.read("thumbnails/Thumbnail.png")
image = tempfile.mkstemp(dir=tempfolder,suffix='.png')[1]
thumb = open(image,"wb")
imagedata = zfile.read("thumbnails/Thumbnail.png")
image = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1]
thumb = open(image, "wb")
thumb.write(imagedata)
thumb.close()
iconbank[filename] = image
@@ -185,7 +192,7 @@ def getInfo(filename):
elif filename.lower().endswith(".fcmacro"):
# For FreeCAD macros, use the Macro Editor icon (but we have to have it in a file for
# the web view to load it)
image = os.path.join(tempfolder,"fcmacro_icon.svg")
image = os.path.join(tempfolder, "fcmacro_icon.svg")
if not os.path.exists(image):
f = QtCore.QFile(":/icons/MacroEditor.svg")
f.copy(image)
@@ -219,19 +226,18 @@ def getInfo(filename):
else:
icon = iconprovider.icon(i)
if icon.availableSizes():
preferred = icon.actualSize(QtCore.QSize(128,128))
preferred = icon.actualSize(QtCore.QSize(128, 128))
px = icon.pixmap(preferred)
image = tempfile.mkstemp(dir=tempfolder,suffix='.png')[1]
image = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1]
px.save(image)
else:
image = getDefaultIcon()
iconbank[t] = image
return [image,size,author,ctime,mtime,descr,company,lic]
return [image, size, author, ctime, mtime, descr, company, lic]
return None
def getDefaultIcon():
"retrieves or creates a default file icon"
@@ -239,52 +245,68 @@ def getDefaultIcon():
global defaulticon
if not defaulticon:
i = QtCore.QFileInfo(__file__) # MUST provide an existing file in qt5
i = QtCore.QFileInfo(__file__) # MUST provide an existing file in qt5
icon = iconprovider.icon(i)
preferred = icon.actualSize(QtCore.QSize(128,128))
preferred = icon.actualSize(QtCore.QSize(128, 128))
px = icon.pixmap(preferred)
image = tempfile.mkstemp(dir=tempfolder,suffix='.png')[1]
image = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1]
px.save(image)
defaulticon = image
return defaulticon
def build_new_file_card(template):
"""builds an html <li> element representing a new file
quick start button"""
templates = {
"empty_file": [TranslationTexts.T_TEMPLATE_EMPTYFILE_NAME, TranslationTexts.T_TEMPLATE_EMPTYFILE_DESC],
"import_file": [TranslationTexts.T_TEMPLATE_IMPORTFILE_NAME, TranslationTexts.T_TEMPLATE_IMPORTFILE_DESC],
"parametric_part": [TranslationTexts.T_TEMPLATE_PARAMETRICPART_NAME, TranslationTexts.T_TEMPLATE_PARAMETRICPART_DESC],
"empty_file": [
TranslationTexts.T_TEMPLATE_EMPTYFILE_NAME,
TranslationTexts.T_TEMPLATE_EMPTYFILE_DESC,
],
"import_file": [
TranslationTexts.T_TEMPLATE_IMPORTFILE_NAME,
TranslationTexts.T_TEMPLATE_IMPORTFILE_DESC,
],
"parametric_part": [
TranslationTexts.T_TEMPLATE_PARAMETRICPART_NAME,
TranslationTexts.T_TEMPLATE_PARAMETRICPART_DESC,
],
# "csg_part": [TranslationTexts.T_TEMPLATE_CSGPART_NAME, TranslationTexts.T_TEMPLATE_CSGPART_DESC],
"2d_draft": [TranslationTexts.T_TEMPLATE_2DDRAFT_NAME, TranslationTexts.T_TEMPLATE_2DDRAFT_DESC],
"architecture": [TranslationTexts.T_TEMPLATE_ARCHITECTURE_NAME, TranslationTexts.T_TEMPLATE_ARCHITECTURE_DESC]
"2d_draft": [
TranslationTexts.T_TEMPLATE_2DDRAFT_NAME,
TranslationTexts.T_TEMPLATE_2DDRAFT_DESC,
],
"architecture": [
TranslationTexts.T_TEMPLATE_ARCHITECTURE_NAME,
TranslationTexts.T_TEMPLATE_ARCHITECTURE_DESC,
],
}
if template not in templates:
return
image = 'file:///'+os.path.join(os.path.join(FreeCAD.getResourceDir(), "Mod", "Start", "StartPage"), 'images/new_'+template+".png").replace('\\','/')
image = "file:///" + os.path.join(
os.path.join(FreeCAD.getResourceDir(), "Mod", "Start", "StartPage"),
"images/new_" + template + ".png",
).replace("\\", "/")
result = ""
result += '<li class="quickstart-button-card">'
result += '<a href="LoadNew.py?template='+urllib.parse.quote(template)+'">'
result += '<img src="'+image+'" alt="'+template+'">'
result += '<a href="LoadNew.py?template=' + urllib.parse.quote(template) + '">'
result += '<img src="' + image + '" alt="' + template + '">'
result += '<div class="caption">'
result += '<h3>'+templates[template][0]+'</h3>'
result += '<p>'+templates[template][1]+'</p>'
result += '</div>'
result += '</a>'
result += '</li>'
result += "<h3>" + templates[template][0] + "</h3>"
result += "<p>" + templates[template][1] + "</p>"
result += "</div>"
result += "</a>"
result += "</li>"
return result
def buildCard(filename,method,arg=None):
def buildCard(filename, method, arg=None):
"""builds an html <li> element representing a file.
method is a script + a keyword, for ex. url.py?key="""
@@ -299,37 +321,41 @@ def buildCard(filename,method,arg=None):
image = finfo[0]
size = finfo[1]
author = finfo[2]
infostring = TranslationTexts.T_CREATIONDATE+": "+finfo[3] + "\n"
infostring += TranslationTexts.T_LASTMODIFIED+": "+finfo[4]
infostring = TranslationTexts.T_CREATIONDATE + ": " + finfo[3] + "\n"
infostring += TranslationTexts.T_LASTMODIFIED + ": " + finfo[4]
if finfo[5]:
infostring += "\n\n" + finfo[5]
if size:
result += '<li class="file-card">'
result += '<a href="'+method+urllib.parse.quote(arg)+'" title="'+infostring+'">'
result += '<img src="file:///'+image.replace('\\','/')+'" alt="'+basename+'">'
result += (
'<a href="' + method + urllib.parse.quote(arg) + '" title="' + infostring + '">'
)
result += (
'<img src="file:///' + image.replace("\\", "/") + '" alt="' + basename + '">'
)
result += '<div class="caption">'
result += '<h4>'+basename+'</h4>'
result += '<p>'+author+'</p>'
result += '<p>'+size+'</p>'
result += '</div>'
result += '</a>'
result += '</li>'
result += "<h4>" + basename + "</h4>"
result += "<p>" + author + "</p>"
result += "<p>" + size + "</p>"
result += "</div>"
result += "</a>"
result += "</li>"
return result
def handle():
"builds the HTML code of the start page"
global iconbank,tempfolder
global iconbank, tempfolder
# reuse stuff from previous runs to reduce temp dir clutter
import Start
if hasattr(Start,"iconbank"):
if hasattr(Start, "iconbank"):
iconbank = Start.iconbank
if hasattr(Start,"tempfolder"):
if hasattr(Start, "tempfolder"):
tempfolder = Start.tempfolder
else:
tempfolder = tempfile.mkdtemp(prefix="FreeCADStartThumbnails")
@@ -338,30 +364,34 @@ def handle():
resources_dir = os.path.join(FreeCAD.getResourceDir(), "Mod", "Start", "StartPage")
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start")
template = p.GetString("Template","")
template = p.GetString("Template", "")
if template:
html_filename = template
else:
html_filename = os.path.join(resources_dir, "StartPage.html")
js_filename = os.path.join(resources_dir, "StartPage.js")
css_filename = p.GetString("CSSFile",os.path.join(resources_dir, "StartPage.css"))
with open(html_filename, 'r') as f:
css_filename = p.GetString("CSSFile", os.path.join(resources_dir, "StartPage.css"))
with open(html_filename, "r") as f:
HTML = f.read()
with open(js_filename, 'r') as f:
with open(js_filename, "r") as f:
JS = f.read()
with open(css_filename, 'r') as f:
with open(css_filename, "r") as f:
CSS = f.read()
HTML = HTML.replace("JS",JS)
HTML = HTML.replace("CSS",CSS)
HTML = HTML.replace("JS", JS)
HTML = HTML.replace("CSS", CSS)
# set the language
HTML = HTML.replace("BCP47_LANGUAGE",QtCore.QLocale().bcp47Name())
HTML = HTML.replace("BCP47_LANGUAGE", QtCore.QLocale().bcp47Name())
# get the stylesheet if we are using one
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool("UseStyleSheet",False):
qssfile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/MainWindow").GetString("StyleSheet","")
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool(
"UseStyleSheet", False
):
qssfile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/MainWindow").GetString(
"StyleSheet", ""
)
if qssfile:
# Search for stylesheet in user, system and resources locations
user = os.path.join(FreeCAD.getUserAppDataDir(), "Gui", "Stylesheets")
@@ -384,38 +414,65 @@ def handle():
f = QtCore.QFile(path)
if f.open(QtCore.QIODevice.ReadOnly | QtCore.QFile.Text):
ALTCSS = QtCore.QTextStream(f).readAll()
HTML = HTML.replace("<!--QSS-->","<style type=\"text/css\">"+ALTCSS+"</style>")
HTML = HTML.replace(
"<!--QSS-->", '<style type="text/css">' + ALTCSS + "</style>"
)
else:
with open(path, 'r') as f:
with open(path, "r") as f:
ALTCSS = f.read()
HTML = HTML.replace("<!--QSS-->","<style type=\"text/css\">"+ALTCSS+"</style>")
HTML = HTML.replace(
"<!--QSS-->", '<style type="text/css">' + ALTCSS + "</style>"
)
# handle file thumbnail icons visibility and size
if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool("ShowFileThumbnailIcons",True):
HTML = HTML.replace("display: block; /* thumb icons display */","display: none; /* thumb icons display */")
HTML = HTML.replace("THUMBCARDSIZE","75px")
if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool(
"ShowFileThumbnailIcons", True
):
HTML = HTML.replace(
"display: block; /* thumb icons display */", "display: none; /* thumb icons display */"
)
HTML = HTML.replace("THUMBCARDSIZE", "75px")
thumb_icons_size = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetInt("FileThumbnailIconsSize", 128)
HTML = HTML.replace("THUMBSIZE",str(thumb_icons_size)+"px")
HTML = HTML.replace("THUMBCARDSIZE",str(thumb_icons_size + 75)+"px")
thumb_icons_size = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetInt(
"FileThumbnailIconsSize", 128
)
HTML = HTML.replace("THUMBSIZE", str(thumb_icons_size) + "px")
HTML = HTML.replace("THUMBCARDSIZE", str(thumb_icons_size + 75) + "px")
# turn tips off if needed
if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool("ShowTips",True):
HTML = HTML.replace("display: block; /* footnote tips display */","display: none; /* footnote tips display */")
if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool(
"ShowTips", True
):
HTML = HTML.replace(
"display: block; /* footnote tips display */",
"display: none; /* footnote tips display */",
)
# get FreeCAD version
v = FreeCAD.Version()
VERSIONSTRING = TranslationTexts.T_VERSION + " " + v[0] + "." + v[1] + "." + v[2] +" " + TranslationTexts.T_BUILD + " " + v[3]
HTML = HTML.replace("VERSIONSTRING",VERSIONSTRING)
VERSIONSTRING = (
TranslationTexts.T_VERSION
+ " "
+ v[0]
+ "."
+ v[1]
+ "."
+ v[2]
+ " "
+ TranslationTexts.T_BUILD
+ " "
+ v[3]
)
HTML = HTML.replace("VERSIONSTRING", VERSIONSTRING)
# translate texts
texts = [t for t in dir(TranslationTexts) if t.startswith("T_")]
for text in texts:
HTML = HTML.replace(text,getattr(TranslationTexts,text))
HTML = HTML.replace(text, getattr(TranslationTexts, text))
# build a "create new" icon with the FreeCAD background color gradient
@@ -426,17 +483,17 @@ def handle():
gradient = QtGui.QLinearGradient(0, 0, 0, 128)
gradient.setColorAt(0.0, QtGui.QColor(c1))
gradient.setColorAt(1.0, QtGui.QColor(c2))
i = QtGui.QImage(128,128,QtGui.QImage.Format_RGB16)
i = QtGui.QImage(128, 128, QtGui.QImage.Format_RGB16)
pa = QtGui.QPainter(i)
pa.fillRect(i.rect(),gradient)
pa.fillRect(i.rect(), gradient)
pa.end()
createimg = tempfile.mkstemp(dir=tempfolder,suffix='.png')[1]
createimg = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1]
i.save(createimg)
iconbank["createimg"] = createimg
# build SECTION_NEW_FILE
SECTION_NEW_FILE = "<h2>"+TranslationTexts.T_NEWFILE+"</h2>"
SECTION_NEW_FILE = "<h2>" + TranslationTexts.T_NEWFILE + "</h2>"
SECTION_NEW_FILE += "<ul>"
SECTION_NEW_FILE += build_new_file_card("empty_file")
SECTION_NEW_FILE += build_new_file_card("import_file")
@@ -444,72 +501,113 @@ def handle():
# SECTION_NEW_FILE += build_new_file_card("csg_part")
SECTION_NEW_FILE += build_new_file_card("2d_draft")
SECTION_NEW_FILE += build_new_file_card("architecture")
SECTION_NEW_FILE += '</ul>'
HTML = HTML.replace("SECTION_NEW_FILE",SECTION_NEW_FILE)
SECTION_NEW_FILE += "</ul>"
HTML = HTML.replace("SECTION_NEW_FILE", SECTION_NEW_FILE)
# build SECTION_RECENTFILES
rf = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/RecentFiles")
rfcount = rf.GetInt("RecentFiles",0)
SECTION_RECENTFILES = "<h2>"+TranslationTexts.T_RECENTFILES+"</h2>"
rfcount = rf.GetInt("RecentFiles", 0)
SECTION_RECENTFILES = "<h2>" + TranslationTexts.T_RECENTFILES + "</h2>"
SECTION_RECENTFILES += "<ul>"
for i in range(rfcount):
filename = rf.GetString("MRU%d" % (i))
SECTION_RECENTFILES += buildCard(filename,method="LoadMRU.py?MRU=",arg=str(i))
SECTION_RECENTFILES += '</ul>'
HTML = HTML.replace("SECTION_RECENTFILES",SECTION_RECENTFILES)
SECTION_RECENTFILES += buildCard(filename, method="LoadMRU.py?MRU=", arg=str(i))
SECTION_RECENTFILES += "</ul>"
HTML = HTML.replace("SECTION_RECENTFILES", SECTION_RECENTFILES)
# build SECTION_EXAMPLES
SECTION_EXAMPLES = ""
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool("ShowExamples",True):
SECTION_EXAMPLES = "<h2>"+TranslationTexts.T_EXAMPLES+"</h2>"
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool(
"ShowExamples", True
):
SECTION_EXAMPLES = "<h2>" + TranslationTexts.T_EXAMPLES + "</h2>"
SECTION_EXAMPLES += "<ul>"
examples_path = FreeCAD.getResourceDir()+"examples"
examples_path = FreeCAD.getResourceDir() + "examples"
if os.path.exists(examples_path):
examples = os.listdir(examples_path)
for basename in examples:
filename = FreeCAD.getResourceDir()+"examples"+os.sep+basename
SECTION_EXAMPLES += buildCard(filename,method="LoadExample.py?filename=")
filename = FreeCAD.getResourceDir() + "examples" + os.sep + basename
SECTION_EXAMPLES += buildCard(filename, method="LoadExample.py?filename=")
SECTION_EXAMPLES += "</ul>"
HTML = HTML.replace("SECTION_EXAMPLES",SECTION_EXAMPLES)
HTML = HTML.replace("SECTION_EXAMPLES", SECTION_EXAMPLES)
# build SECTION_CUSTOM
SECTION_CUSTOM = ""
cfolders = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetString("ShowCustomFolder","")
cfolders = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetString(
"ShowCustomFolder", ""
)
if cfolders:
dn = 0
for cfolder in cfolders.split(";;"): # allow several paths separated by ;;
for cfolder in cfolders.split(";;"): # allow several paths separated by ;;
if not os.path.isdir(cfolder):
cfolder = os.path.dirname(cfolder)
if not os.path.exists(cfolder):
FreeCAD.Console.PrintWarning("Custom folder not found: %s" % cfolder)
else:
SECTION_CUSTOM += "<h2>"+os.path.basename(os.path.normpath(cfolder))+"</h2>"
SECTION_CUSTOM += "<h2>" + os.path.basename(os.path.normpath(cfolder)) + "</h2>"
SECTION_CUSTOM += "<ul>"
for basename in os.listdir(cfolder):
filename = os.path.join(cfolder,basename)
SECTION_CUSTOM += buildCard(filename,method="LoadCustom.py?filename="+str(dn)+"_")
filename = os.path.join(cfolder, basename)
SECTION_CUSTOM += buildCard(
filename, method="LoadCustom.py?filename=" + str(dn) + "_"
)
SECTION_CUSTOM += "</ul>"
# hide the custom section tooltip if custom section is set (users know about it if they enabled it)
HTML = HTML.replace("id=\"customtip\" class","id=\"customtip\" style=\"display:none;\" class")
HTML = HTML.replace(
'id="customtip" class', 'id="customtip" style="display:none;" class'
)
dn += 1
HTML = HTML.replace("SECTION_CUSTOM",SECTION_CUSTOM)
HTML = HTML.replace("SECTION_CUSTOM", SECTION_CUSTOM)
# build IMAGE_SRC paths
HTML = HTML.replace("IMAGE_SRC_FREECAD",'file:///'+os.path.join(resources_dir, 'images/freecad.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_ICON_DOCUMENTS",'file:///'+os.path.join(resources_dir, 'images/icon_documents.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_ICON_HELP",'file:///'+os.path.join(resources_dir, 'images/icon_help.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_ICON_ACTIVITY",'file:///'+os.path.join(resources_dir, 'images/icon_activity.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_ICON_BLOG",'file:///'+os.path.join(resources_dir, 'images/icon_blog.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_USERHUB",'file:///'+os.path.join(resources_dir, 'images/userhub.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_POWERHUB",'file:///'+os.path.join(resources_dir, 'images/poweruserhub.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_DEVHUB",'file:///'+os.path.join(resources_dir, 'images/developerhub.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_MANUAL",'file:///'+os.path.join(resources_dir, 'images/manual.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_SETTINGS",'file:///'+os.path.join(resources_dir, 'images/icon_settings.png').replace('\\','/'))
HTML = HTML.replace("IMAGE_SRC_INSTALLED",'file:///'+os.path.join(resources_dir, 'images/installed.png').replace('\\','/'))
HTML = HTML.replace(
"IMAGE_SRC_FREECAD",
"file:///" + os.path.join(resources_dir, "images/freecad.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_ICON_DOCUMENTS",
"file:///" + os.path.join(resources_dir, "images/icon_documents.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_ICON_HELP",
"file:///" + os.path.join(resources_dir, "images/icon_help.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_ICON_ACTIVITY",
"file:///" + os.path.join(resources_dir, "images/icon_activity.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_ICON_BLOG",
"file:///" + os.path.join(resources_dir, "images/icon_blog.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_USERHUB",
"file:///" + os.path.join(resources_dir, "images/userhub.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_POWERHUB",
"file:///" + os.path.join(resources_dir, "images/poweruserhub.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_DEVHUB",
"file:///" + os.path.join(resources_dir, "images/developerhub.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_MANUAL",
"file:///" + os.path.join(resources_dir, "images/manual.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_SETTINGS",
"file:///" + os.path.join(resources_dir, "images/icon_settings.png").replace("\\", "/"),
)
HTML = HTML.replace(
"IMAGE_SRC_INSTALLED",
"file:///" + os.path.join(resources_dir, "images/installed.png").replace("\\", "/"),
)
# build UL_WORKBENCHES
@@ -554,28 +652,43 @@ def handle():
if wb in iconbank:
img = iconbank[wb]
else:
img = os.path.join(FreeCAD.getResourceDir(),"Mod",wn,"Resources","icons",wn+"Workbench.svg")
img = os.path.join(
FreeCAD.getResourceDir(), "Mod", wn, "Resources", "icons", wn + "Workbench.svg"
)
if not os.path.exists(img):
w = FreeCADGui.listWorkbenches()[wb]
if hasattr(w,"Icon") and w.Icon:
if hasattr(w, "Icon") and w.Icon:
xpm = w.Icon
if "XPM" in xpm:
xpm = xpm.replace("\n ","\n") # some XPMs have some indent that QT doesn't like
r = [s[:-1].strip('"') for s in re.findall("(?s){(.*?)};",xpm)[0].split("\n")[1:]]
xpm = xpm.replace(
"\n ", "\n"
) # some XPMs have some indent that QT doesn't like
r = [
s[:-1].strip('"')
for s in re.findall("(?s){(.*?)};", xpm)[0].split("\n")[1:]
]
p = QtGui.QPixmap(r)
p = p.scaled(24,24)
img = tempfile.mkstemp(dir=tempfolder,suffix='.png')[1]
p = p.scaled(24, 24)
img = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1]
p.save(img)
else:
img = xpm
else:
img = os.path.join(resources_dir,"images/freecad.png")
img = os.path.join(resources_dir, "images/freecad.png")
iconbank[wb] = img
UL_WORKBENCHES += '<li>'
UL_WORKBENCHES += '<img src="file:///'+img.replace('\\','/')+'" alt="'+wn+'">&nbsp;'
UL_WORKBENCHES += '<a href="https://www.freecad.org/wiki/'+wn+'_Workbench">'+wn.replace("Reverse_Engineering","ReverseEng")+'</a>'
UL_WORKBENCHES += '</li>'
UL_WORKBENCHES += '</ul>'
UL_WORKBENCHES += "<li>"
UL_WORKBENCHES += (
'<img src="file:///' + img.replace("\\", "/") + '" alt="' + wn + '">&nbsp;'
)
UL_WORKBENCHES += (
'<a href="https://www.freecad.org/wiki/'
+ wn
+ '_Workbench">'
+ wn.replace("Reverse_Engineering", "ReverseEng")
+ "</a>"
)
UL_WORKBENCHES += "</li>"
UL_WORKBENCHES += "</ul>"
HTML = HTML.replace("UL_WORKBENCHES", UL_WORKBENCHES)
# Detect additional addons that are not a workbench
@@ -598,56 +711,69 @@ def handle():
pass
else:
wblist.append("cadexchanger")
HTML = HTML.replace("var wblist = [];","var wblist = " + str(wblist) + ";")
HTML = HTML.replace("var wblist = [];", "var wblist = " + str(wblist) + ";")
# set and replace colors and font settings
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start")
if p.GetString("BackgroundImage",""):
BACKGROUND = gethexcolor(p.GetUnsigned("BackgroundColor1",1331197183))+" url("+p.GetString("BackgroundImage","")+")"
if p.GetString("BackgroundImage", ""):
BACKGROUND = (
gethexcolor(p.GetUnsigned("BackgroundColor1", 1331197183))
+ " url("
+ p.GetString("BackgroundImage", "")
+ ")"
)
else:
BACKGROUND = gethexcolor(p.GetUnsigned("BackgroundColor1",1331197183))
BACKGROUND = gethexcolor(p.GetUnsigned("BackgroundColor1", 1331197183))
# linear gradient not supported by QT "linear-gradient("+gethexcolor(p.GetUnsigned("BackgroundColor1",1331197183))+","+gethexcolor(p.GetUnsigned("BackgroundColor2",2141107711))+")"
LINKCOLOR = gethexcolor(p.GetUnsigned("LinkColor",65535))
BASECOLOR = gethexcolor(p.GetUnsigned("PageColor",4294967295))
BOXCOLOR = gethexcolor(p.GetUnsigned("BoxColor",3722305023))
TEXTCOLOR = gethexcolor(p.GetUnsigned("PageTextColor",255))
BGTCOLOR = gethexcolor(p.GetUnsigned("BackgroundTextColor",1600086015))
OVERFLOW = "" if p.GetBool("ShowScrollBars",True) else "body::-webkit-scrollbar {display: none;}"
LINKCOLOR = gethexcolor(p.GetUnsigned("LinkColor", 65535))
BASECOLOR = gethexcolor(p.GetUnsigned("PageColor", 4294967295))
BOXCOLOR = gethexcolor(p.GetUnsigned("BoxColor", 3722305023))
TEXTCOLOR = gethexcolor(p.GetUnsigned("PageTextColor", 255))
BGTCOLOR = gethexcolor(p.GetUnsigned("BackgroundTextColor", 1600086015))
OVERFLOW = (
"" if p.GetBool("ShowScrollBars", True) else "body::-webkit-scrollbar {display: none;}"
)
SHADOW = "#888888"
if QtGui.QColor(BASECOLOR).valueF() < 0.5: # dark page - we need to make darker shadows
if QtGui.QColor(BASECOLOR).valueF() < 0.5: # dark page - we need to make darker shadows
SHADOW = "#000000"
FONTFAMILY = p.GetString("FontFamily","Arial,Helvetica,sans")
FONTFAMILY = p.GetString("FontFamily", "Arial,Helvetica,sans")
if not FONTFAMILY:
FONTFAMILY = "Arial,Helvetica,sans"
FONTSIZE = p.GetInt("FontSize",13)
HTML = HTML.replace("BASECOLOR",BASECOLOR)
HTML = HTML.replace("BOXCOLOR",BOXCOLOR)
HTML = HTML.replace("LINKCOLOR",LINKCOLOR)
HTML = HTML.replace("TEXTCOLOR",TEXTCOLOR)
HTML = HTML.replace("BGTCOLOR",BGTCOLOR)
HTML = HTML.replace("BACKGROUND",BACKGROUND)
HTML = HTML.replace("SHADOW",SHADOW)
HTML = HTML.replace("FONTFAMILY",FONTFAMILY)
HTML = HTML.replace("FONTSIZE",str(FONTSIZE)+"px")
HTML = HTML.replace("OVERFLOW",OVERFLOW)
FONTSIZE = p.GetInt("FontSize", 13)
HTML = HTML.replace("BASECOLOR", BASECOLOR)
HTML = HTML.replace("BOXCOLOR", BOXCOLOR)
HTML = HTML.replace("LINKCOLOR", LINKCOLOR)
HTML = HTML.replace("TEXTCOLOR", TEXTCOLOR)
HTML = HTML.replace("BGTCOLOR", BGTCOLOR)
HTML = HTML.replace("BACKGROUND", BACKGROUND)
HTML = HTML.replace("SHADOW", SHADOW)
HTML = HTML.replace("FONTFAMILY", FONTFAMILY)
HTML = HTML.replace("FONTSIZE", str(FONTSIZE) + "px")
HTML = HTML.replace("OVERFLOW", OVERFLOW)
# enable web access if permitted
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool("AllowDownload",False):
HTML = HTML.replace("var allowDownloads = 0;","var allowDownloads = 1;")
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool(
"AllowDownload", False
):
HTML = HTML.replace("var allowDownloads = 0;", "var allowDownloads = 1;")
# enable or disable forum
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool("ShowForum",False):
HTML = HTML.replace("var showForum = 0;","var showForum = 1;")
HTML = HTML.replace("display: none; /* forum display */","display: block; /* forum display */")
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool("ShowForum", False):
HTML = HTML.replace("var showForum = 0;", "var showForum = 1;")
HTML = HTML.replace(
"display: none; /* forum display */", "display: block; /* forum display */"
)
# enable or disable notepad
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool("ShowNotes",False):
HTML = HTML.replace("display: none; /* notes display */","display: block; /* notes display */")
HTML = HTML.replace("width: 100%; /* thumbs display */","width: 70%; /* thumbs display */")
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool("ShowNotes", False):
HTML = HTML.replace(
"display: none; /* notes display */", "display: block; /* notes display */"
)
HTML = HTML.replace("width: 100%; /* thumbs display */", "width: 70%; /* thumbs display */")
# store variables for further use
@@ -657,18 +783,16 @@ def handle():
return HTML
def exportTestFile():
"Allow to check if everything is Ok"
f = open(os.path.expanduser("~")+os.sep+"freecad-startpage.html","w")
f = open(os.path.expanduser("~") + os.sep + "freecad-startpage.html", "w")
f.write(handle())
f.close()
def postStart(switch_wb = True):
def postStart(switch_wb=True):
"executes needed operations after loading a file"
@@ -676,18 +800,22 @@ def postStart(switch_wb = True):
# switch workbench
if switch_wb:
wb = param.GetString("AutoloadModule","")
wb = param.GetString("AutoloadModule", "")
if "$LastModule" == wb:
wb = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/General").GetString("LastModule","")
wb = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/General").GetString(
"LastModule", ""
)
if wb:
# don't switch workbenches if we are not in Start anymore
if FreeCADGui.activeWorkbench() and (FreeCADGui.activeWorkbench().name() == "StartWorkbench"):
if FreeCADGui.activeWorkbench() and (
FreeCADGui.activeWorkbench().name() == "StartWorkbench"
):
FreeCADGui.activateWorkbench(wb)
# close start tab
cl = param.GetBool("closeStart",False)
cl = param.GetBool("closeStart", False)
if cl:
title = QtGui.QApplication.translate("Workbench","Start page")
title = QtGui.QApplication.translate("Workbench", "Start page")
mw = FreeCADGui.getMainWindow()
if mw:
mdi = mw.findChild(QtGui.QMdiArea)
@@ -698,13 +826,15 @@ def postStart(switch_wb = True):
subw.close()
def checkPostOpenStartPage():
"on Start WB startup, check if we are loading a file and therefore need to close the StartPage"
import Start
if FreeCAD.ParamGet('User parameter:BaseApp/Preferences/Mod/Start').GetBool('DoNotShowOnOpen',False) and (not hasattr(Start,'CanOpenStartPage')):
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Start").GetBool(
"DoNotShowOnOpen", False
) and (not hasattr(Start, "CanOpenStartPage")):
if len(sys.argv) > 1:
postStart()
Start.CanOpenStartPage = True

View File

@@ -1,28 +1,28 @@
#***************************************************************************
#* Copyright (c) 2012 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * Copyright (c) 2012 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
from PySide import QtGui
def translate(context,text):
def translate(context, text):
"convenience function for the Qt translator"
@@ -34,6 +34,7 @@ def translate(context,text):
return u.replace(chr(39), "&rsquo;")
T_TITLE = translate("StartPage", "Start")
T_WELCOME = translate("StartPage", "Welcome to FreeCAD")
T_DOCUMENTS = translate("StartPage", "Documents")
@@ -47,7 +48,9 @@ T_TEMPLATE_EMPTYFILE_DESC = translate("StartPage", "Create an empty FreeCAD file
T_TEMPLATE_IMPORTFILE_NAME = translate("StartPage", "Import File")
T_TEMPLATE_IMPORTFILE_DESC = translate("StartPage", "Work on an existing CAD file or 3D model")
T_TEMPLATE_PARAMETRICPART_NAME = translate("StartPage", "Standard Part")
T_TEMPLATE_PARAMETRICPART_DESC = translate("StartPage", "Create a part with the Part Design workbench")
T_TEMPLATE_PARAMETRICPART_DESC = translate(
"StartPage", "Create a part with the Part Design workbench"
)
# T_TEMPLATE_CSGPART_NAME = translate("StartPage", "CSG Part")
# T_TEMPLATE_CSGPART_DESC = translate("StartPage", "Create a part with the Part workbench")
T_TEMPLATE_2DDRAFT_NAME = translate("StartPage", "2D Draft")
@@ -56,38 +59,85 @@ T_TEMPLATE_ARCHITECTURE_NAME = translate("StartPage", "BIM/Architecture")
T_TEMPLATE_ARCHITECTURE_DESC = translate("StartPage", "Create an architecture project")
T_RECENTFILES = translate("StartPage", "Recent files")
T_TIP = translate("StartPage", "Tip")
T_ADJUSTRECENT = translate("StartPage", "Adjust the number of recent files to be shown here in menu Edit -> Preferences -> General -> Size of recent file list")
T_ADJUSTRECENT = translate(
"StartPage",
"Adjust the number of recent files to be shown here in menu Edit -> Preferences -> General -> Size of recent file list",
)
T_EXAMPLES = translate("StartPage", "Examples")
T_GENERALDOCUMENTATION = translate("StartPage", "General documentation")
T_USERHUB = translate("StartPage", "User hub")
T_DESCR_USERHUB = translate("StartPage", "This section contains documentation useful for FreeCAD users in general: a list of all the workbenches, detailed instructions on how to install and use the FreeCAD application, tutorials, and all you need to get started.")
T_DESCR_USERHUB = translate(
"StartPage",
"This section contains documentation useful for FreeCAD users in general: a list of all the workbenches, detailed instructions on how to install and use the FreeCAD application, tutorials, and all you need to get started.",
)
T_POWERHUB = translate("StartPage", "Power users hub")
T_DESCR_POWERHUB = translate("StartPage", "This section gathers documentation for advanced users and people interested in writing python scripts. You will also find there a repository of macros, instructions on how to install and use them, and more information about customizing FreeCAD to your specific needs.")
T_DESCR_POWERHUB = translate(
"StartPage",
"This section gathers documentation for advanced users and people interested in writing python scripts. You will also find there a repository of macros, instructions on how to install and use them, and more information about customizing FreeCAD to your specific needs.",
)
T_DEVHUB = translate("StartPage", "Developers hub")
T_DESCR_DEVHUB = translate("StartPage", "This section contains material for developers: How to compile FreeCAD yourself, how the FreeCAD source code is structured + how to navigate in it, how to develop new workbenches and/or embed FreeCAD in your own application.")
T_DESCR_DEVHUB = translate(
"StartPage",
"This section contains material for developers: How to compile FreeCAD yourself, how the FreeCAD source code is structured + how to navigate in it, how to develop new workbenches and/or embed FreeCAD in your own application.",
)
T_MANUAL = translate("StartPage", "Manual")
T_DESCR_MANUAL = translate("StartPage", "The FreeCAD manual is another, more linear way to present the information contained in this wiki. It is made to be read like a book, and will gently introduce you to many other pages from the hubs above. <a href=\"https://www.gitbook.com/book/yorikvanhavre/a-freecad-manual/details\">e-book versions</a> are also available.")
T_DESCR_MANUAL = translate(
"StartPage",
'The FreeCAD manual is another, more linear way to present the information contained in this wiki. It is made to be read like a book, and will gently introduce you to many other pages from the hubs above. <a href="https://www.gitbook.com/book/yorikvanhavre/a-freecad-manual/details">e-book versions</a> are also available.',
)
T_WBHELP = translate("StartPage", "Workbenches documentation")
T_DESCR_WBHELP = translate("StartPage", "These are the help pages of all the workbenches currently installed on this computer.")
T_DESCR_WBHELP = translate(
"StartPage",
"These are the help pages of all the workbenches currently installed on this computer.",
)
T_COMMUNITYHELP = translate("StartPage", "Getting help from the community")
T_DESCR_COMMUNITYHELP1 = translate("StartPage", "The <a href=\"http://forum.freecad.org\">FreeCAD forum</a> is a great place to get help from other FreeCAD users and developers. The forum has many sections for different types of issues and discussion subjects. If in doubt, post in the more general <a href=\"https://forum.freecad.org/viewforum.php?f=3\">Help on using FreeCAD</a> section.")
T_DESCR_COMMUNITYHELP2 = translate("StartPage", "If it is the first time you are posting on the forum, be sure to <a href=\"https://forum.freecad.org/viewtopic.php?f=3&t=2264\">read the guidelines</a> first!")
T_DESCR_COMMUNITYHELP3 = translate("StartPage", "FreeCAD also maintains a public <a href=\"https://www.freecad.org/tracker\">bug tracker</a> where anybody can submit bugs and propose new features. To avoid causing extra work and give the best chances to see your bug solved, make sure you read the <a href=\"https://forum.freecad.org/viewtopic.php?f=3&t=5236\">bug submission guide</a> before posting.")
T_DESCR_COMMUNITYHELP1 = translate(
"StartPage",
'The <a href="http://forum.freecad.org">FreeCAD forum</a> is a great place to get help from other FreeCAD users and developers. The forum has many sections for different types of issues and discussion subjects. If in doubt, post in the more general <a href="https://forum.freecad.org/viewforum.php?f=3">Help on using FreeCAD</a> section.',
)
T_DESCR_COMMUNITYHELP2 = translate(
"StartPage",
'If it is the first time you are posting on the forum, be sure to <a href="https://forum.freecad.org/viewtopic.php?f=3&t=2264">read the guidelines</a> first!',
)
T_DESCR_COMMUNITYHELP3 = translate(
"StartPage",
'FreeCAD also maintains a public <a href="https://www.freecad.org/tracker">bug tracker</a> where anybody can submit bugs and propose new features. To avoid causing extra work and give the best chances to see your bug solved, make sure you read the <a href="https://forum.freecad.org/viewtopic.php?f=3&t=5236">bug submission guide</a> before posting.',
)
T_ADDONS = translate("StartPage", "Available addons")
T_DESCR_ADDONS = translate("StartPage", "Below is a list of available extra workbenches that can be added to your FreeCAD installation. Browse and install them from menu Tools -> Addons manager. You can learn more about any of them by clicking the links below.")
T_OFFLINEHELP = translate("StartPage", "If not bundled with your FreeCAD version, install the FreeCAD documentation package to get documentation hubs, workbench help and individual command documentation without an internet connection.")
T_OFFLINEPLACEHOLDER = translate("StartPage", "Cannot fetch information from GitHub. <a href=\"EnableDownload.py\">Authorize FreeCAD to access the internet</a> and reload the Start page.")
T_DESCR_ADDONS = translate(
"StartPage",
"Below is a list of available extra workbenches that can be added to your FreeCAD installation. Browse and install them from menu Tools -> Addons manager. You can learn more about any of them by clicking the links below.",
)
T_OFFLINEHELP = translate(
"StartPage",
"If not bundled with your FreeCAD version, install the FreeCAD documentation package to get documentation hubs, workbench help and individual command documentation without an internet connection.",
)
T_OFFLINEPLACEHOLDER = translate(
"StartPage",
'Cannot fetch information from GitHub. <a href="EnableDownload.py">Authorize FreeCAD to access the internet</a> and reload the Start page.',
)
T_RECENTCOMMITS = translate("StartPage", "Recent commits")
T_DESCR_RECENTCOMMITS = translate("StartPage", "Below are the latest changes added to the <a href=\"http://github.com/FreeCAD/FreeCAD/\">FreeCAD source code</a>. These changes might not reflect yet in the FreeCAD version that you are currently running. Check the <a href=\"https://www.freecad.org/wiki/Downloads\">available options</a> if you wish to obtain a development version.")
T_DESCR_RECENTCOMMITS = translate(
"StartPage",
'Below are the latest changes added to the <a href="http://github.com/FreeCAD/FreeCAD/">FreeCAD source code</a>. These changes might not reflect yet in the FreeCAD version that you are currently running. Check the <a href="https://www.freecad.org/wiki/Downloads">available options</a> if you wish to obtain a development version.',
)
T_SEEONGITHUB = translate("StartPage", "See all commits on github")
T_CUSTOM = translate("StartPage", "You can configure a custom folder to display here in menu Edit -> Preferences -> Start -> Show additional folder")
T_CUSTOM = translate(
"StartPage",
"You can configure a custom folder to display here in menu Edit -> Preferences -> Start -> Show additional folder",
)
T_VERSION = translate("StartPage", "version")
T_BUILD = translate("StartPage", "build")
T_CREATENEW = translate("StartPage", "Create new...")
T_UNKNOWN = translate("StartPage", "Unknown")
T_FORUM = translate("StartPage", "Forum")
T_DESCR_FORUM = translate("StartPage", "The latest posts on the <a href=\"https://forum.freecad.org\">FreeCAD forum</a>:")
T_EXTERNALLINKS = translate("StartPage", "To open any of the links above in your desktop browser, Right-click -> Open in external browser")
T_DESCR_FORUM = translate(
"StartPage", 'The latest posts on the <a href="https://forum.freecad.org">FreeCAD forum</a>:'
)
T_EXTERNALLINKS = translate(
"StartPage",
"To open any of the links above in your desktop browser, Right-click -> Open in external browser",
)
T_CREATIONDATE = translate("StartPage", "Creation date")
T_LASTMODIFIED = translate("StartPage", "Last modification")
T_NOTES = translate("StartPage", "Notes")

View File

@@ -26,53 +26,96 @@ import Start
from StartPage import StartPage
import re
class TestStartPage(unittest.TestCase):
"""Basic validation of the generated Start page."""
MODULE = 'TestStartPage' # file name without extension
MODULE = "TestStartPage" # file name without extension
def setUp(self):
pass
def test_all_css_placeholders_removed(self):
"""Check to see if all of the CSS placeholders have been replaced."""
placeholders = ["BACKGROUND","BGTCOLOR","FONTFAMILY","FONTSIZE","LINKCOLOR",
"TEXTCOLOR","BOXCOLOR","BASECOLOR","SHADOW"]
placeholders = [
"BACKGROUND",
"BGTCOLOR",
"FONTFAMILY",
"FONTSIZE",
"LINKCOLOR",
"TEXTCOLOR",
"BOXCOLOR",
"BASECOLOR",
"SHADOW",
]
page = StartPage.handle()
for placeholder in placeholders:
self.assertNotIn (placeholder, page, "{} was not removed from the CSS".format(placeholder))
self.assertNotIn(
placeholder, page, "{} was not removed from the CSS".format(placeholder)
)
def test_all_js_placeholders_removed(self):
"""Check to see if all of the JavaScript placeholders have been replaced."""
placeholders = ["IMAGE_SRC_INSTALLED"]
page = StartPage.handle()
for placeholder in placeholders:
self.assertNotIn (placeholder, page, "{} was not removed from the JS".format(placeholder))
self.assertNotIn(
placeholder, page, "{} was not removed from the JS".format(placeholder)
)
def test_all_html_placeholders_removed(self):
"""Check to see if all of the HTML placeholders have been replaced."""
placeholders = ["T_TITLE","VERSIONSTRING","T_DOCUMENTS","T_HELP","T_ACTIVITY",
"SECTION_RECENTFILES","T_TIP","T_ADJUSTRECENT","SECTION_EXAMPLES",
"SECTION_CUSTOM","T_CUSTOM","T_NOTES","T_GENERALDOCUMENTATION",
"IMAGE_SRC_USERHUB", "T_USERHUB", "T_DESCR_USERHUB",
"IMAGE_SRC_POWERHUB","T_POWERHUB","T_DESCR_POWERHUB",
"IMAGE_SRC_DEVHUB", "T_DEVHUB", "T_DESCR_DEVHUB",
"IMAGE_SRC_MANUAL", "T_MANUAL", "T_DESCR_MANUAL",
"T_WBHELP","T_DESCR_WBHELP","UL_WORKBENCHES",
"T_COMMUNITYHELP","T_DESCR_COMMUNITYHELP1","T_DESCR_COMMUNITYHELP2",
"T_DESCR_COMMUNITYHELP3","T_ADDONS","T_DESCR_ADDONS",
"T_OFFLINEPLACEHOLDER","T_OFFLINEHELP","T_EXTERNALLINKS",
"T_RECENTCOMMITS","T_DESCR_RECENTCOMMITS","T_EXTERNALLINKS",
"T_SEEONGITHUB","T_FORUM","T_DESCR_FORUM"]
placeholders = [
"T_TITLE",
"VERSIONSTRING",
"T_DOCUMENTS",
"T_HELP",
"T_ACTIVITY",
"SECTION_RECENTFILES",
"T_TIP",
"T_ADJUSTRECENT",
"SECTION_EXAMPLES",
"SECTION_CUSTOM",
"T_CUSTOM",
"T_NOTES",
"T_GENERALDOCUMENTATION",
"IMAGE_SRC_USERHUB",
"T_USERHUB",
"T_DESCR_USERHUB",
"IMAGE_SRC_POWERHUB",
"T_POWERHUB",
"T_DESCR_POWERHUB",
"IMAGE_SRC_DEVHUB",
"T_DEVHUB",
"T_DESCR_DEVHUB",
"IMAGE_SRC_MANUAL",
"T_MANUAL",
"T_DESCR_MANUAL",
"T_WBHELP",
"T_DESCR_WBHELP",
"UL_WORKBENCHES",
"T_COMMUNITYHELP",
"T_DESCR_COMMUNITYHELP1",
"T_DESCR_COMMUNITYHELP2",
"T_DESCR_COMMUNITYHELP3",
"T_ADDONS",
"T_DESCR_ADDONS",
"T_OFFLINEPLACEHOLDER",
"T_OFFLINEHELP",
"T_EXTERNALLINKS",
"T_RECENTCOMMITS",
"T_DESCR_RECENTCOMMITS",
"T_EXTERNALLINKS",
"T_SEEONGITHUB",
"T_FORUM",
"T_DESCR_FORUM",
]
page = StartPage.handle()
for placeholder in placeholders:
self.assertNotIn (placeholder, page, "{} was not removed from the HTML".format(placeholder))
self.assertNotIn(
placeholder, page, "{} was not removed from the HTML".format(placeholder)
)
def test_files_do_not_contain_backslashes(self):
# This would be caught by the W3C validator if we didn't sanitize the filenames before sending them.
@@ -86,15 +129,19 @@ class TestStartPage(unittest.TestCase):
badFilenames.append(result)
if len(badFilenames) > 0:
self.fail("The following filenames contain backslashes, which is prohibited in HTML: {}".format(badFilenames))
self.fail(
"The following filenames contain backslashes, which is prohibited in HTML: {}".format(
badFilenames
)
)
def test_html_validates(self):
# Send the generated html to the W3C validator for analysis (removing potentially-sensitive data first)
import urllib.request
import os
import json
page = self.sanitize(StartPage.handle()) # Remove potentially sensitive data
page = self.sanitize(StartPage.handle()) # Remove potentially sensitive data
# For debugging, if you want to ensure that the sanitization worked correctly:
# from pathlib import Path
@@ -104,15 +151,15 @@ class TestStartPage(unittest.TestCase):
# f.close()
validation_url = "https://validator.w3.org/nu/?out=json"
data = page.encode('utf-8') # data should be bytes
data = page.encode("utf-8") # data should be bytes
req = urllib.request.Request(validation_url, data)
req.add_header("Content-type","text/html; charset=utf-8")
req.add_header("Content-type", "text/html; charset=utf-8")
errorCount = 0
warningCount = 0
infoCount = 0
validationResultString = ""
try:
with urllib.request.urlopen (req) as response:
with urllib.request.urlopen(req) as response:
text = response.read()
responseJSON = json.loads(text)
@@ -123,15 +170,23 @@ class TestStartPage(unittest.TestCase):
if "subtype" in message:
if message["subtype"] == "warning":
warningCount += 1
validationResultString += "WARNING: {}\n".format(ascii(message["message"]))
validationResultString += "WARNING: {}\n".format(
ascii(message["message"])
)
else:
infoCount += 1
validationResultString += "INFO: {}\n".format(ascii(message["message"]))
validationResultString += "INFO: {}\n".format(
ascii(message["message"])
)
elif message["type"] == "error":
errorCount += 1
validationResultString += "ERROR: {}\n".format(ascii(message["message"]))
validationResultString += "ERROR: {}\n".format(
ascii(message["message"])
)
elif message["type"] == "non-document-error":
FreeCAD.Console.PrintWarning("W3C validator returned a non-document error:\n {}".format(message))
FreeCAD.Console.PrintWarning(
"W3C validator returned a non-document error:\n {}".format(message)
)
return
except urllib.error.HTTPError as e:
@@ -142,27 +197,37 @@ class TestStartPage(unittest.TestCase):
if errorCount > 0 or warningCount > 0:
StartPage.exportTestFile()
FreeCAD.Console.PrintWarning("HTML validation failed: Start page source written to your home directory for analysis.")
self.fail("W3C Validator analysis shows the Start page has {} errors and {} warnings:\n\n{}".format(errorCount, warningCount, validationResultString))
FreeCAD.Console.PrintWarning(
"HTML validation failed: Start page source written to your home directory for analysis."
)
self.fail(
"W3C Validator analysis shows the Start page has {} errors and {} warnings:\n\n{}".format(
errorCount, warningCount, validationResultString
)
)
elif infoCount > 0:
FreeCAD.Console.PrintWarning("The Start page is valid HTML, but the W3C sent back {} informative messages:\n{}.".format(infoCount,validationResultString))
FreeCAD.Console.PrintWarning(
"The Start page is valid HTML, but the W3C sent back {} informative messages:\n{}.".format(
infoCount, validationResultString
)
)
def sanitize (self, html):
def sanitize(self, html):
# Anonymize all local filenames
fileRE = re.compile(r'"file:///.*?"')
html = fileRE.sub(repl=r'"file:///A/B/C"', string=html)
# Anonymize titles, which are used for mouseover text and might contain document information
titleRE = re.compile(r'title="[\s\S]*?"') # Some titles have newlines in them
titleRE = re.compile(r'title="[\s\S]*?"') # Some titles have newlines in them
html = titleRE.sub(repl=r'title="Y"', string=html)
# Anonymize the document names, which we display in <h4> tags
h4RE = re.compile(r'<h4>.*?</h4>')
html = h4RE.sub(repl=r'<h4>Z</h4>', string=html)
h4RE = re.compile(r"<h4>.*?</h4>")
html = h4RE.sub(repl=r"<h4>Z</h4>", string=html)
# Remove any simple single-line paragraphs, which might contain document author information, file size information, etc.
pRE = re.compile(r'<p>[^<]*?</p>')
html = pRE.sub(repl=r'<p>X</p>', string=html)
pRE = re.compile(r"<p>[^<]*?</p>")
html = pRE.sub(repl=r"<p>X</p>", string=html)
return html