From: Jakob Haufe Date: Mon, 31 Mar 2025 10:42:16 +0000 (+0200) Subject: New upstream version 0.11.0 X-Git-Tag: debian/0.11.0-1~7 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=25b935eb199abe52da5c47fbfe64ba838df83d0d;p=fstl New upstream version 0.11.0 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 0628afa..fe586c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ #### Fast .stl viewer ##### -# Original Project Author: Matt Keeter Copyright 2014 -2017 -# Author: Paul Tsouchlos Copyright 2017 +# Original Project Author: Matt Keeter Copyright 2014-2024 +# Author: Paul Tsouchlos Copyright 2017-2024 cmake_minimum_required(VERSION 3.3) @@ -13,7 +13,7 @@ set(CXX_STANDARD_REQUIRED ON) # Set the version number set (FSTL_VERSION_MAJOR "0") -set (FSTL_VERSION_MINOR "10") +set (FSTL_VERSION_MINOR "11") set (FSTL_VERSION_PATCH "0") set (PROJECT_VERSION "${FSTL_VERSION_MAJOR}.${FSTL_VERSION_MINOR}.${FSTL_VERSION_PATCH}") @@ -32,7 +32,8 @@ src/glmesh.cpp src/loader.cpp src/main.cpp src/mesh.cpp -src/window.cpp) +src/window.cpp +src/shaderlightprefs.cpp) #set project headers. set(Project_Headers src/app.h @@ -42,7 +43,8 @@ src/canvas.h src/glmesh.h src/loader.h src/mesh.h -src/window.h) +src/window.h +src/shaderlightprefs.h) #set project resources and icon resource set(Project_Resources qt/qt.qrc gl/gl.qrc) diff --git a/gl/gl.qrc b/gl/gl.qrc index 6e8baa9..a806530 100644 --- a/gl/gl.qrc +++ b/gl/gl.qrc @@ -4,6 +4,7 @@ mesh.vert mesh_wireframe.frag mesh_surfaceangle.frag + mesh_light.frag quad.frag quad.vert colored_lines.frag diff --git a/gl/mesh_light.frag b/gl/mesh_light.frag new file mode 100644 index 0000000..31d43bb --- /dev/null +++ b/gl/mesh_light.frag @@ -0,0 +1,26 @@ +#version 120 + +uniform float zoom; +uniform vec4 ambient_light_color; +uniform vec4 directive_light_color; +uniform vec3 directive_light_direction; + +varying vec3 ec_pos; + +void main() { + // Normalize light direction + vec3 dir = normalize(directive_light_direction); + + // vec3 a = vec3(0.0, 1.0, 1.0); + // normal vector + vec3 ec_normal = normalize(cross(dFdx(ec_pos), dFdy(ec_pos))); + ec_normal.z *= zoom; + ec_normal = normalize(ec_normal); + + + vec3 color = ambient_light_color.w * ambient_light_color.xyz + directive_light_color.w * dot(ec_normal,dir) * directive_light_color.xyz; + + // float coef = dot(ec_normal,dir); + // vec3 color = coef * lightcolor + (1.0 - coef) * objectcolor; + gl_FragColor = vec4(color, 1.0); +} diff --git a/qt/icons/fstl_64x64.png b/qt/icons/fstl_64x64.png new file mode 100644 index 0000000..2a63e41 Binary files /dev/null and b/qt/icons/fstl_64x64.png differ diff --git a/qt/qt.qrc b/qt/qt.qrc index 883ac14..f2b1266 100644 --- a/qt/qt.qrc +++ b/qt/qt.qrc @@ -1,5 +1,6 @@ - + style.qss + icons/fstl_64x64.png diff --git a/src/app.cpp b/src/app.cpp index a76a7da..07de99e 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "app.h" #include "window.h" @@ -7,10 +8,17 @@ App::App(int& argc, char *argv[]) : QApplication(argc, argv), window(new Window()) { - if (argc > 1) - window->load_stl(argv[1]); + if (argc > 1) { + QString filename = argv[1]; + if (filename.startsWith("~")) { + filename.replace(0, 1, QDir::homePath()); + } + window->load_stl(filename); + } else + { window->load_stl(":gl/sphere.stl"); + } window->show(); } diff --git a/src/canvas.cpp b/src/canvas.cpp index 4da41a7..ad4ec37 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -11,9 +11,21 @@ const float Canvas::P_PERSPECTIVE = 0.25f; const float Canvas::P_ORTHOGRAPHIC = 0.0f; +const QString Canvas::AMBIENT_COLOR = "ambientColor"; +const QString Canvas::AMBIENT_FACTOR = "ambientFactor"; +const QString Canvas::DIRECTIVE_COLOR = "directiveColor"; +const QString Canvas::DIRECTIVE_FACTOR = "directiveFactor"; +const QString Canvas::CURRENT_LIGHT_DIRECTION = "currentLightDirection"; + +const QColor Canvas::defaultAmbientColor = QColor::fromRgbF(0.22,0.8,1.0); +const QColor Canvas::defaultDirectiveColor = QColor(255,255,255); +const float Canvas::defaultAmbientFactor = 0.67; +const float Canvas::defaultDirectiveFactor = 0.5; +const int Canvas::defaultCurrentLightDirection = 1; + Canvas::Canvas(const QSurfaceFormat& format, QWidget *parent) : QOpenGLWidget(parent), mesh(nullptr), - scale(1), zoom(1), tilt(90), yaw(0), + scale(1), zoom(1), anim(this, "perspective"), status(" "), meshInfo("") { @@ -21,6 +33,38 @@ Canvas::Canvas(const QSurfaceFormat& format, QWidget *parent) QFile styleFile(":/qt/style.qss"); styleFile.open( QFile::ReadOnly ); setStyleSheet(styleFile.readAll()); + currentTransform = QMatrix4x4(); + resetTransform(); + + QSettings settings; + ambientColor = settings.value(AMBIENT_COLOR,defaultAmbientColor).value(); + directiveColor = settings.value(DIRECTIVE_COLOR,defaultDirectiveColor).value(); + ambientFactor = settings.value(AMBIENT_FACTOR,defaultAmbientFactor).value(); + directiveFactor = settings.value(DIRECTIVE_FACTOR,defaultDirectiveFactor).value(); + + // Fill direction list + // Fill in directions + nameDir.clear(); + listDir.clear(); + QList xname, yname, zname; + xname << "right " << " " << "left "; + yname << "top " << " " << "bottom "; + zname << "rear " << " " << "front "; + for (int i=-1; i<2 ; i++) { + for (int j=-1; j<2; j++) { + for (int k=-1; k<2; k++) { + QString current = xname.at(i+1) + yname.at(j+1) + zname.at(k+1); + if (!(i==0 && j==0 && k==0)) { + nameDir << current.simplified(); + listDir << QVector3D((double)i,(double)j,(double)k); + } + } + } + } + currentLightDirection = settings.value(CURRENT_LIGHT_DIRECTION,defaultCurrentLightDirection).value(); + if (currentLightDirection < 0 || currentLightDirection >= nameDir.length()) { + currentLightDirection = defaultCurrentLightDirection; + } anim.setDuration(100); } @@ -42,6 +86,65 @@ void Canvas::view_anim(float v) anim.start(); } +void Canvas::common_view_change(enum ViewPoint c) +{ + if (c == centerview) { + scale = default_scale; + center = default_center; + zoom = 1; + update(); + return; + } + + currentTransform.setToIdentity(); + currentTransform.rotate(180.0, QVector3D(0, 0, 1)); + + switch (c) + { + case isoview: + { + currentTransform.rotate(90, QVector3D(1, 0, 0)); + currentTransform.rotate(-45, QVector3D(0, 0, 1)); + currentTransform.rotate(35.264, QVector3D(1, 1, 0)); + } + break; + case topview: + { + currentTransform.rotate(180, QVector3D(1, 0, 0)); + } + break; + case leftview: + { + currentTransform.rotate(180, QVector3D(1, 0, 0)); + currentTransform.rotate(90, QVector3D(0, 0, 1)); + currentTransform.rotate(90, QVector3D(0, 1, 0)); + } + break; + case rightview: + { + currentTransform.rotate(180, QVector3D(1, 0, 0)); + currentTransform.rotate(-90.0, QVector3D(0, 1, 0)); + currentTransform.rotate(-90, QVector3D(1, 0, 0)); + } + break; + case frontview: + { + currentTransform.rotate(90, QVector3D(1, 0, 0)); + } + break; + case backview: + { + currentTransform.rotate(90, QVector3D(1, 0, 0)); + currentTransform.rotate(180, QVector3D(0, 0, 1)); + } + case bottomview: + [[fallthrough]]; + default: + break; + } + update(); +} + void Canvas::view_perspective(float p, bool animate){ if(animate) { @@ -65,6 +168,20 @@ void Canvas::invert_zoom(bool d) update(); } +void Canvas::setResetTransformOnLoad(bool d) { + resetTransformOnLoad = d; +} + +void Canvas::resetTransform() { + currentTransform.setToIdentity(); + // apply some rotations to define initial orientation + currentTransform.rotate(-90.0, QVector3D(1, 0, 0)); + currentTransform.rotate(180.0 + 15.0, QVector3D(0, 0, 1)); + currentTransform.rotate(15.0, QVector3D(1, -sin(M_PI/12), 0)); + + zoom = 1; +} + void Canvas::load_mesh(Mesh* m, bool is_reload) { delete mesh; @@ -73,13 +190,14 @@ void Canvas::load_mesh(Mesh* m, bool is_reload) QVector3D upper(m->xmax(), m->ymax(), m->zmax()); if (!is_reload) { - center = (lower + upper) / 2; - scale = 2 / (upper - lower).length(); + default_center = center = (lower + upper) / 2; + default_scale = scale = 2 / (upper - lower).length(); // Reset other camera parameters zoom = 1; - yaw = 0; - tilt = 90; + if (resetTransformOnLoad) { + resetTransform(); + } } meshInfo = QStringLiteral("Triangles: %1\nX: [%2, %3]\nY: [%4, %5]\nZ: [%6, %7]").arg(m->triCount()); for(int dIdx = 0; dIdx < 3; dIdx++) meshInfo = meshInfo.arg(lower[dIdx]).arg(upper[dIdx]); @@ -128,6 +246,9 @@ void Canvas::initializeGL() mesh_surfaceangle_shader.addShader(mesh_vertshader); mesh_surfaceangle_shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/gl/mesh_surfaceangle.frag"); mesh_surfaceangle_shader.link(); + mesh_meshlight_shader.addShader(mesh_vertshader); + mesh_meshlight_shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/gl/mesh_light.frag"); + mesh_meshlight_shader.link(); backdrop = new Backdrop(); axis = new Axis(); @@ -165,10 +286,14 @@ void Canvas::draw_mesh() { selected_mesh_shader = &mesh_shader; } - else + else if (drawMode == surfaceangle) { selected_mesh_shader = &mesh_surfaceangle_shader; } + else if (drawMode == meshlight) + { + selected_mesh_shader = &mesh_meshlight_shader; + } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } @@ -185,6 +310,28 @@ void Canvas::draw_mesh() // Compensate for z-flattening when zooming glUniform1f(selected_mesh_shader->uniformLocation("zoom"), 1/zoom); + // specific meshlight arguments + if (drawMode == meshlight) { + // Ambient Light Color, followed by the ambient light coefficient to use + //glUniform4f(selected_mesh_shader->uniformLocation("ambient_light_color"),0.22f, 0.8f, 1.0f, 0.67f); + glUniform4f(selected_mesh_shader->uniformLocation("ambient_light_color"),ambientColor.redF(), ambientColor.greenF(), ambientColor.blueF(), ambientFactor); + // Directive Light Color, followed by the directive light coefficient to use + //glUniform4f(selected_mesh_shader->uniformLocation("directive_light_color"),1.0f,1.0f,1.0f,0.5f); + glUniform4f(selected_mesh_shader->uniformLocation("directive_light_color"),directiveColor.redF(),directiveColor.greenF(),directiveColor.blueF(),directiveFactor); + + // Directive Light Direction + // dir 1,0,0 Light from the left + // dir -1,0,0 Light from the right + // dir 0,1,0 Light from bottom + // dir 0,-1,0 Light from top + // dir 0,0,1 Light from viewer (front) + // dir 0,0,-1 Light from behind + // + // -1,-1,0 Light from top right + //glUniform3f(selected_mesh_shader->uniformLocation("directive_light_direction"),-1.0f,-1.0f,0.0f); + glUniform3f(selected_mesh_shader->uniformLocation("directive_light_direction"),listDir.at(currentLightDirection).x(), listDir.at(currentLightDirection).y(), listDir.at(currentLightDirection).z()); + } + // Find and enable the attribute location for vertex position const GLuint vp = selected_mesh_shader->attributeLocation("vertex_position"); glEnableVertexAttribArray(vp); @@ -201,11 +348,7 @@ void Canvas::draw_mesh() } QMatrix4x4 Canvas::orient_matrix() const { - QMatrix4x4 m; - m.rotate(tilt, QVector3D(1, 0, 0)); - m.rotate(yaw, QVector3D(0, 0, 1)); - //We want the x axis to the right, and the z axis up - m.scale(-1, 1, -1); + QMatrix4x4 m = currentTransform; return m; } QMatrix4x4 Canvas::transform_matrix() const @@ -255,16 +398,72 @@ void Canvas::mouseReleaseEvent(QMouseEvent* event) } } + +// This method change the referential of the mouse point coordinates +// into a referential x=[-1.0,1.0], y=[-1.0,1.0], with 0,0 being the +// center of the widget. +QPointF Canvas::changeMouseCoordinates(QPoint p) { + QPointF pr; + // Change coordinates + double ws2 = this->width() / 2.0; + double hs2 = this->height() / 2.0; + pr.setX(p.x() / ws2 - 1.0); + pr.setY(p.y() / hs2 - 1.0); + return pr; +} + +void Canvas::calcArcballTransform(QPointF p1, QPointF p2) { + // Calc z1 & z2 + double x1 = p1.x(); + double x2 = p2.x(); + double y1 = p1.y(); + double y2 = p2.y(); + double p1sq = x1 * x1 + y1 * y1; + double z1; + if (p1sq <= 1) { + z1 = sqrt(1.0 - p1sq); + } else { + x1 = x1 / sqrt(p1sq); + y1 = y1 / sqrt(p1sq); + z1 = 0.0; + } + double p2sq = x2 * x2 + y2 * y2; + double z2; + if (p2sq <= 1) { + z2 = sqrt(1.0 - p2sq); + } else { + x2 = x2 / sqrt(p2sq); + y2 = y2 / sqrt(p2sq); + z2 = 0.0; + } + + // set v1 and v2 + QVector3D v1(x1, y1, z1); + QVector3D v2(x2, y2, z2); + + // calc v1 cross v2 + QVector3D v1xv2 = QVector3D::crossProduct(v1, v2); + QVector3D v1xv2Obj = currentTransform.inverted().mapVector(v1xv2); + + // calc angle + double angle = acos(std::min(1.0f,QVector3D::dotProduct(v1, v2))) * 180.0 / M_PI; + + // apply transform + currentTransform.rotate(angle,v1xv2Obj); +} + void Canvas::mouseMoveEvent(QMouseEvent* event) { auto p = event->pos(); auto d = p - mouse_pos; - + if (event->buttons() & Qt::LeftButton) { - yaw = fmod(yaw - d.x(), 360); - tilt = fmod(tilt - d.y(), 360); + QPointF p1r = changeMouseCoordinates(mouse_pos); + QPointF p2r = changeMouseCoordinates(p); + calcArcballTransform(p1r,p2r); + update(); } else if (event->buttons() & Qt::RightButton) @@ -316,3 +515,71 @@ void Canvas::resizeGL(int width, int height) { glViewport(0, 0, width, height); } + +QColor Canvas::getAmbientColor() { + return ambientColor; +} + +void Canvas::setAmbientColor(QColor c) { + ambientColor = c; + QSettings settings; + settings.setValue(AMBIENT_COLOR,c); +} + +double Canvas::getAmbientFactor() { + return (float) ambientFactor; +} + +void Canvas::setAmbientFactor(double f) { + ambientFactor = (float) f; + QSettings settings; + settings.setValue(AMBIENT_FACTOR,f); +} + +void Canvas::resetAmbientColor() { + setAmbientColor(defaultAmbientColor); + setAmbientFactor(defaultAmbientFactor); +} + +QColor Canvas::getDirectiveColor() { + return directiveColor; +} + +void Canvas::setDirectiveColor(QColor c) { + directiveColor = c; + QSettings settings; + settings.setValue(DIRECTIVE_COLOR,c); +} + +double Canvas::getDirectiveFactor() { + return (float) directiveFactor; +} + +void Canvas::setDirectiveFactor(double f) { + directiveFactor = (float) f; + QSettings settings; + settings.setValue(DIRECTIVE_FACTOR,f); +} + +void Canvas::resetDirectiveColor() { + setDirectiveColor(defaultDirectiveColor); + setDirectiveFactor(defaultDirectiveFactor); +} + +QList Canvas::getNameDir() { + return nameDir; +} + +int Canvas::getCurrentLightDirection() { + return currentLightDirection; +} + +void Canvas::setCurrentLightDirection(int ind) { + currentLightDirection = ind; + QSettings settings; + settings.setValue(CURRENT_LIGHT_DIRECTION,currentLightDirection); +} + +void Canvas::resetCurrentLightDirection() { + setCurrentLightDirection(defaultCurrentLightDirection); +} diff --git a/src/canvas.h b/src/canvas.h index 0fdff64..8dab30c 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -10,7 +10,8 @@ class Mesh; class Backdrop; class Axis; -enum DrawMode {shaded, wireframe, surfaceangle, DRAWMODECOUNT}; +enum ViewPoint {centerview, isoview, topview, bottomview, leftview, rightview, frontview, backview}; +enum DrawMode {shaded, wireframe, surfaceangle, meshlight, DRAWMODECOUNT}; class Canvas : public QOpenGLWidget, protected QOpenGLFunctions { @@ -27,6 +28,25 @@ public: void draw_axes(bool d); void invert_zoom(bool d); void set_drawMode(enum DrawMode mode); + void common_view_change(enum ViewPoint c); + void setResetTransformOnLoad(bool d); + + QColor getAmbientColor(); + void setAmbientColor(QColor c); + double getAmbientFactor(); + void setAmbientFactor(double f); + void resetAmbientColor(); + + QColor getDirectiveColor(); + void setDirectiveColor(QColor c); + double getDirectiveFactor(); + void setDirectiveFactor(double f); + void resetDirectiveColor(); + + QList getNameDir(); + int getCurrentLightDirection(); + void setCurrentLightDirection(int ind); + void resetCurrentLightDirection(); public slots: void set_status(const QString& s); @@ -53,26 +73,50 @@ private: QMatrix4x4 transform_matrix() const; QMatrix4x4 aspect_matrix() const; QMatrix4x4 view_matrix() const; + void resetTransform(); + QPointF changeMouseCoordinates(QPoint p); + void calcArcballTransform(QPointF p1, QPointF p2); QOpenGLShader* mesh_vertshader; QOpenGLShaderProgram mesh_shader; QOpenGLShaderProgram mesh_wireframe_shader; QOpenGLShaderProgram mesh_surfaceangle_shader; + QOpenGLShaderProgram mesh_meshlight_shader; + + QColor ambientColor; + QColor directiveColor; + float ambientFactor; + float directiveFactor; + QList nameDir; + QList listDir; + int currentLightDirection; + + const static QColor defaultAmbientColor; + const static QColor defaultDirectiveColor; + const static float defaultAmbientFactor; + const static float defaultDirectiveFactor; + const static int defaultCurrentLightDirection; + const static QString AMBIENT_COLOR; + const static QString AMBIENT_FACTOR; + const static QString DIRECTIVE_COLOR; + const static QString DIRECTIVE_FACTOR; + const static QString CURRENT_LIGHT_DIRECTION; + GLMesh* mesh; Backdrop* backdrop; Axis* axis; - QVector3D center; - float scale; + QVector3D center, default_center; + float scale, default_scale; float zoom; - float tilt; - float yaw; + QMatrix4x4 currentTransform; float perspective; enum DrawMode drawMode; bool drawAxes; bool invertZoom; + bool resetTransformOnLoad; Q_PROPERTY(float perspective MEMBER perspective WRITE set_perspective); QPropertyAnimation anim; diff --git a/src/loader.cpp b/src/loader.cpp index 38bd2dd..58b81a1 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -116,6 +116,15 @@ Mesh* Loader::load_stl() return NULL; } + qint64 file_size, file_size_old; + file_size = file.size(); + do { + file_size_old = file_size; + QThread::usleep(100000); + file_size = file.size(); + } + while(file_size != file_size_old); + // First, try to read the stl as an ASCII file if (file.read(5) == "solid") { diff --git a/src/main.cpp b/src/main.cpp index 4ec8722..14561eb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,10 +4,14 @@ int main(int argc, char *argv[]) { + // Force C locale to force decimal point + QLocale::setDefault(QLocale::c()); + QCoreApplication::setOrganizationName("fstl-app"); QCoreApplication::setOrganizationDomain("https://github.com/fstl-app/fstl"); QCoreApplication::setApplicationName("fstl"); QCoreApplication::setApplicationVersion(FSTL_VERSION); App a(argc, argv); + return a.exec(); } diff --git a/src/shaderlightprefs.cpp b/src/shaderlightprefs.cpp new file mode 100644 index 0000000..d00c707 --- /dev/null +++ b/src/shaderlightprefs.cpp @@ -0,0 +1,180 @@ +#include "shaderlightprefs.h" +#include "canvas.h" +#include + +const QString ShaderLightPrefs::PREFS_GEOM = "shaderPrefsGeometry"; + +ShaderLightPrefs::ShaderLightPrefs(QWidget *parent, Canvas *_canvas) : QDialog(parent) +{ + canvas = _canvas; + + QVBoxLayout* prefsLayout = new QVBoxLayout; + this->setLayout(prefsLayout); + + QLabel* title = new QLabel("Shader preferences"); + QFont boldFont = QApplication::font(); + boldFont.setWeight(QFont::Bold); + title->setFont(boldFont); + title->setAlignment(Qt::AlignCenter); + prefsLayout->addWidget(title); + + QWidget* middleWidget = new QWidget; + QGridLayout* middleLayout = new QGridLayout; + middleWidget->setLayout(middleLayout); + this->layout()->addWidget(middleWidget); + + // labels + middleLayout->addWidget(new QLabel("Ambient Color"),0,0); + middleLayout->addWidget(new QLabel("Directive Color"),1,0); + middleLayout->addWidget(new QLabel("Direction"),2,0); + + QPixmap dummy(20, 20); + + dummy.fill(canvas->getAmbientColor()); + buttonAmbientColor = new QPushButton; + buttonAmbientColor->setIcon(QIcon(dummy)); + middleLayout->addWidget(buttonAmbientColor,0,1); + buttonAmbientColor->setFocusPolicy(Qt::NoFocus); + connect(buttonAmbientColor,SIGNAL(clicked(bool)),this,SLOT(buttonAmbientColorClicked())); + + editAmbientFactor = new QLineEdit; + editAmbientFactor->setValidator(new QDoubleValidator); + editAmbientFactor->setText(QString("%1").arg(canvas->getAmbientFactor())); + middleLayout->addWidget(editAmbientFactor,0,2); + connect(editAmbientFactor,SIGNAL(editingFinished()),this,SLOT(editAmbientFactorFinished())); + + QPushButton* buttonResetAmbientColor = new QPushButton("Reset"); + middleLayout->addWidget(buttonResetAmbientColor,0,3); + buttonResetAmbientColor->setFocusPolicy(Qt::NoFocus); + connect(buttonResetAmbientColor,SIGNAL(clicked(bool)),this,SLOT(resetAmbientColorClicked())); + + + dummy.fill(canvas->getDirectiveColor()); + buttonDirectiveColor = new QPushButton; + buttonDirectiveColor->setIcon(QIcon(dummy)); + middleLayout->addWidget(buttonDirectiveColor,1,1); + buttonDirectiveColor->setFocusPolicy(Qt::NoFocus); + connect(buttonDirectiveColor,SIGNAL(clicked(bool)),this,SLOT(buttonDirectiveColorClicked())); + + editDirectiveFactor = new QLineEdit; + editDirectiveFactor->setValidator(new QDoubleValidator); + editDirectiveFactor->setText(QString("%1").arg(canvas->getDirectiveFactor())); + middleLayout->addWidget(editDirectiveFactor,1,2); + connect(editDirectiveFactor,SIGNAL(editingFinished()),this,SLOT(editDirectiveFactorFinished())); + + QPushButton* buttonResetDirectiveColor = new QPushButton("Reset"); + middleLayout->addWidget(buttonResetDirectiveColor,1,3); + buttonResetDirectiveColor->setFocusPolicy(Qt::NoFocus); + connect(buttonResetDirectiveColor,SIGNAL(clicked(bool)),this,SLOT(resetDirectiveColorClicked())); + + // Fill in directions + + comboDirections = new QComboBox; + middleLayout->addWidget(comboDirections,2,1,1,2); + comboDirections->addItems(canvas->getNameDir()); + comboDirections->setCurrentIndex(canvas->getCurrentLightDirection()); + connect(comboDirections,SIGNAL(currentIndexChanged(int)),this,SLOT(comboDirectionsChanged(int))); + + QPushButton* buttonResetDirection = new QPushButton("Reset"); + middleLayout->addWidget(buttonResetDirection,2,3); + buttonResetDirection->setFocusPolicy(Qt::NoFocus); + connect(buttonResetDirection,SIGNAL(clicked(bool)),this,SLOT(resetDirection())); + + + // Ok button + QWidget* boxButton = new QWidget; + QHBoxLayout* boxButtonLayout = new QHBoxLayout; + boxButton->setLayout(boxButtonLayout); + QFrame *spacerL = new QFrame; + spacerL->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding)); + QPushButton* okButton = new QPushButton("Ok"); + boxButtonLayout->addWidget(spacerL); + boxButtonLayout->addWidget(okButton); + this->layout()->addWidget(boxButton); + okButton->setFocusPolicy(Qt::NoFocus); + connect(okButton,SIGNAL(clicked(bool)),this,SLOT(okButtonClicked())); + + QSettings settings; + if (!settings.value(PREFS_GEOM).isNull()) { + restoreGeometry(settings.value(PREFS_GEOM).toByteArray()); + } +} + +void ShaderLightPrefs::buttonAmbientColorClicked() { + QColor newColor = QColorDialog::getColor(canvas->getAmbientColor(), this, QString("Choose color"),QColorDialog::DontUseNativeDialog); + if (newColor.isValid() == true) + { + canvas->setAmbientColor(newColor); + QPixmap dummy(20, 20); + dummy.fill(canvas->getAmbientColor()); + buttonAmbientColor->setIcon(QIcon(dummy)); + canvas->update(); + } +} + +void ShaderLightPrefs::editAmbientFactorFinished() { + canvas->setAmbientFactor(editAmbientFactor->text().toDouble()); + canvas->update(); +} + +void ShaderLightPrefs::resetAmbientColorClicked() { + canvas->resetAmbientColor(); + QPixmap dummy(20, 20); + dummy.fill(canvas->getAmbientColor()); + buttonAmbientColor->setIcon(QIcon(dummy)); + editAmbientFactor->setText(QString("%1").arg(canvas->getAmbientFactor())); + canvas->update(); +} + +void ShaderLightPrefs::buttonDirectiveColorClicked() { + QColor newColor = QColorDialog::getColor(canvas->getDirectiveColor(), this, QString("Choose color"),QColorDialog::DontUseNativeDialog); + if (newColor.isValid() == true) + { + canvas->setDirectiveColor(newColor); + QPixmap dummy(20, 20); + dummy.fill(canvas->getDirectiveColor()); + buttonDirectiveColor->setIcon(QIcon(dummy)); + canvas->update(); + } +} + +void ShaderLightPrefs::editDirectiveFactorFinished() { + canvas->setDirectiveFactor(editDirectiveFactor->text().toDouble()); + canvas->update(); +} + +void ShaderLightPrefs::resetDirectiveColorClicked() { + canvas->resetDirectiveColor(); + QPixmap dummy(20, 20); + dummy.fill(canvas->getDirectiveColor()); + buttonDirectiveColor->setIcon(QIcon(dummy)); + editDirectiveFactor->setText(QString("%1").arg(canvas->getDirectiveFactor())); + canvas->update(); +} + +void ShaderLightPrefs::okButtonClicked() { + this->close(); +} + +void ShaderLightPrefs::comboDirectionsChanged(int ind) { + canvas->setCurrentLightDirection(ind); + canvas->update(); +} + +void ShaderLightPrefs::resetDirection() { + canvas->resetCurrentLightDirection(); + comboDirections->setCurrentIndex(canvas->getCurrentLightDirection()); + canvas->update(); +} + +void ShaderLightPrefs::resizeEvent(QResizeEvent *event) +{ + QSettings().setValue(PREFS_GEOM, saveGeometry()); +} + +void ShaderLightPrefs::moveEvent(QMoveEvent *event) +{ + QSettings().setValue(PREFS_GEOM, saveGeometry()); +} + + diff --git a/src/shaderlightprefs.h b/src/shaderlightprefs.h new file mode 100644 index 0000000..9f57339 --- /dev/null +++ b/src/shaderlightprefs.h @@ -0,0 +1,46 @@ +#ifndef SHADERLIGHTPREFS_H +#define SHADERLIGHTPREFS_H + +#include + +class Canvas; +class QLabel; +class QLineEdit; +class QComboBox; + +class ShaderLightPrefs : public QDialog +{ + Q_OBJECT +public: + ShaderLightPrefs(QWidget* parent, Canvas* _canvas); + +protected: + void resizeEvent(QResizeEvent *event) override; + void moveEvent(QMoveEvent *event) override; + +private slots: + void buttonAmbientColorClicked(); + void editAmbientFactorFinished(); + void resetAmbientColorClicked(); + + void buttonDirectiveColorClicked(); + void editDirectiveFactorFinished(); + void resetDirectiveColorClicked(); + + void comboDirectionsChanged(int ind); + void resetDirection(); + + void okButtonClicked(); + +private: + Canvas* canvas; + QPushButton* buttonAmbientColor; + QLineEdit* editAmbientFactor; + QPushButton* buttonDirectiveColor; + QLineEdit* editDirectiveFactor; + QComboBox* comboDirections; + + const static QString PREFS_GEOM; +}; + +#endif // SHADERLIGHTPREFS_H diff --git a/src/window.cpp b/src/window.cpp index e9f3f94..c8aaba7 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -3,7 +3,9 @@ #include "window.h" #include "canvas.h" #include "loader.h" +#include "shaderlightprefs.h" +const QString Window::OPEN_EXTERNAL_KEY = "externalCmd"; const QString Window::RECENT_FILE_KEY = "recentFiles"; const QString Window::INVERT_ZOOM_KEY = "invertZoom"; const QString Window::AUTORELOAD_KEY = "autoreload"; @@ -11,23 +13,37 @@ const QString Window::DRAW_AXES_KEY = "drawAxes"; const QString Window::PROJECTION_KEY = "projection"; const QString Window::DRAW_MODE_KEY = "drawMode"; const QString Window::WINDOW_GEOM_KEY = "windowGeometry"; +const QString Window::RESET_TRANSFORM_ON_LOAD_KEY = "resetTransformOnLoad"; Window::Window(QWidget *parent) : QMainWindow(parent), open_action(new QAction("Open", this)), + open_external_action(new QAction("Open with", this)), about_action(new QAction("About", this)), quit_action(new QAction("Quit", this)), perspective_action(new QAction("Perspective", this)), + common_view_center_action(new QAction("Center the model", this)), + common_view_iso_action(new QAction("Isometric", this)), + common_view_top_action(new QAction("Top", this)), + common_view_bottom_action(new QAction("Bottom", this)), + common_view_left_action(new QAction("Left", this)), + common_view_right_action(new QAction("Right", this)), + common_view_front_action(new QAction("Front", this)), + common_view_back_action(new QAction("Back", this)), orthographic_action(new QAction("Orthographic", this)), shaded_action(new QAction("Shaded", this)), wireframe_action(new QAction("Wireframe", this)), surfaceangle_action(new QAction("Surface Angle", this)), + meshlight_action(new QAction("Shaded ambient and directive light source", this)), + drawModePrefs_action(new QAction("Draw Mode Settings")), axes_action(new QAction("Draw Axes", this)), invert_zoom_action(new QAction("Invert Zoom", this)), reload_action(new QAction("Reload", this)), autoreload_action(new QAction("Autoreload", this)), save_screenshot_action(new QAction("Save Screenshot", this)), hide_menuBar_action(new QAction("Hide Menu Bar", this)), + fullscreen_action(new QAction("Toggle Fullscreen",this)), + resetTransformOnLoadAction(new QAction("Reset rotation on load",this)), recent_files(new QMenu("Open recent", this)), recent_files_group(new QActionGroup(this)), recent_files_clear_action(new QAction("Clear recent files", this)), @@ -35,6 +51,7 @@ Window::Window(QWidget *parent) : { setWindowTitle("fstl"); + setWindowIcon(QIcon(":/qt/icons/fstl_64x64.png")); setAcceptDrops(true); QSurfaceFormat format; @@ -48,6 +65,10 @@ Window::Window(QWidget *parent) : canvas = new Canvas(format, this); setCentralWidget(canvas); + meshlightprefs = new ShaderLightPrefs(this, canvas); + + QObject::connect(drawModePrefs_action, &QAction::triggered,this,&Window::on_drawModePrefs); + QObject::connect(watcher, &QFileSystemWatcher::fileChanged, this, &Window::on_watched_change); @@ -56,7 +77,13 @@ Window::Window(QWidget *parent) : this, &Window::on_open); this->addAction(open_action); - quit_action->setShortcut(QKeySequence::Quit); + open_external_action->setShortcut(QKeySequence::Open); + QObject::connect(open_external_action, &QAction::triggered, this, &Window::on_open_external); + this->addAction(open_external_action); + open_external_action->setShortcut(QKeySequence(Qt::ALT + Qt::Key_S)); + + QList quitShortcuts = { QKeySequence::Quit, QKeySequence::Close }; + quit_action->setShortcuts(quitShortcuts); QObject::connect(quit_action, &QAction::triggered, this, &Window::close); this->addAction(quit_action); @@ -84,8 +111,9 @@ Window::Window(QWidget *parent) : rebuild_recent_files(); - auto file_menu = menuBar()->addMenu("File"); + const auto file_menu = menuBar()->addMenu("File"); file_menu->addAction(open_action); + file_menu->addAction(open_external_action); file_menu->addMenu(recent_files); file_menu->addSeparator(); file_menu->addAction(reload_action); @@ -93,11 +121,11 @@ Window::Window(QWidget *parent) : file_menu->addAction(save_screenshot_action); file_menu->addAction(quit_action); - auto view_menu = menuBar()->addMenu("View"); - auto projection_menu = view_menu->addMenu("Projection"); + const auto view_menu = menuBar()->addMenu("View"); + const auto projection_menu = view_menu->addMenu("Projection"); projection_menu->addAction(perspective_action); projection_menu->addAction(orthographic_action); - auto projections = new QActionGroup(projection_menu); + const auto projections = new QActionGroup(projection_menu); for (auto p : {perspective_action, orthographic_action}) { projections->addAction(p); @@ -107,12 +135,13 @@ Window::Window(QWidget *parent) : QObject::connect(projections, &QActionGroup::triggered, this, &Window::on_projection); - auto draw_menu = view_menu->addMenu("Draw Mode"); + const auto draw_menu = view_menu->addMenu("Draw Mode"); draw_menu->addAction(shaded_action); draw_menu->addAction(wireframe_action); draw_menu->addAction(surfaceangle_action); - auto drawModes = new QActionGroup(draw_menu); - for (auto p : {shaded_action, wireframe_action, surfaceangle_action}) + draw_menu->addAction(meshlight_action); + const auto drawModes = new QActionGroup(draw_menu); + for (auto p : {shaded_action, wireframe_action, surfaceangle_action, meshlight_action}) { drawModes->addAction(p); p->setCheckable(true); @@ -120,6 +149,38 @@ Window::Window(QWidget *parent) : drawModes->setExclusive(true); QObject::connect(drawModes, &QActionGroup::triggered, this, &Window::on_drawMode); + view_menu->addAction(drawModePrefs_action); + drawModePrefs_action->setDisabled(true); + + const auto common_menu = view_menu->addMenu("Viewpoint"); + common_menu->addAction(common_view_iso_action); + common_menu->addAction(common_view_top_action); + common_menu->addAction(common_view_bottom_action); + common_menu->addAction(common_view_front_action); + common_menu->addAction(common_view_back_action); + common_menu->addAction(common_view_left_action); + common_menu->addAction(common_view_right_action); + common_menu->addAction(common_view_center_action); + const auto common_views = new QActionGroup(common_menu); + common_views->addAction(common_view_iso_action); + common_views->addAction(common_view_top_action); + common_views->addAction(common_view_bottom_action); + common_views->addAction(common_view_front_action); + common_views->addAction(common_view_back_action); + common_views->addAction(common_view_left_action); + common_views->addAction(common_view_right_action); + common_views->addAction(common_view_center_action); + common_view_iso_action->setShortcut(Qt::Key_0); + common_view_top_action->setShortcut(Qt::Key_1); + common_view_bottom_action->setShortcut(Qt::Key_2); + common_view_front_action->setShortcut(Qt::Key_3); + common_view_back_action->setShortcut(Qt::Key_4); + common_view_left_action->setShortcut(Qt::Key_5); + common_view_right_action->setShortcut(Qt::Key_6); + common_view_center_action->setShortcut(Qt::Key_9); + QObject::connect(common_views, &QActionGroup::triggered, + this, &Window::on_common_view_change); + view_menu->addAction(axes_action); axes_action->setCheckable(true); QObject::connect(axes_action, &QAction::triggered, @@ -130,6 +191,11 @@ Window::Window(QWidget *parent) : QObject::connect(invert_zoom_action, &QAction::triggered, this, &Window::on_invertZoom); + view_menu->addAction(resetTransformOnLoadAction); + resetTransformOnLoadAction->setCheckable(true); + QObject::connect(resetTransformOnLoadAction, &QAction::triggered, + this, &Window::on_resetTransformOnLoad); + view_menu->addAction(hide_menuBar_action); hide_menuBar_action->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_C); hide_menuBar_action->setCheckable(true); @@ -137,6 +203,14 @@ Window::Window(QWidget *parent) : this, &Window::on_hide_menuBar); this->addAction(hide_menuBar_action); + view_menu->addAction(fullscreen_action); + fullscreen_action->setShortcut(Qt::Key_F11); + fullscreen_action->setCheckable(true); + QObject::connect(fullscreen_action, &QAction::toggled, + this, &Window::on_fullscreen); + this->addAction(fullscreen_action); + + auto help_menu = menuBar()->addMenu("Help"); help_menu->addAction(about_action); @@ -149,6 +223,10 @@ void Window::load_persist_settings(){ canvas->invert_zoom(invert_zoom); invert_zoom_action->setChecked(invert_zoom); + bool resetTransformOnLoad = settings.value(RESET_TRANSFORM_ON_LOAD_KEY, true).toBool(); + canvas->setResetTransformOnLoad(resetTransformOnLoad); + resetTransformOnLoadAction->setChecked(resetTransformOnLoad); + autoreload_action->setChecked(settings.value(AUTORELOAD_KEY, true).toBool()); bool draw_axes = settings.value(DRAW_AXES_KEY, false).toBool(); @@ -164,30 +242,73 @@ void Window::load_persist_settings(){ orthographic_action->setChecked(true); } + QString path = settings.value(OPEN_EXTERNAL_KEY, "").toString(); + if (!QDir::isAbsolutePath(path) && !path.isEmpty()) + { + path = QStandardPaths::findExecutable(path); + } + QString displayName = path.mid(path.lastIndexOf(QDir::separator()) + 1); + open_external_action->setText("Open with " + displayName); + open_external_action->setData(path); + DrawMode draw_mode = (DrawMode)settings.value(DRAW_MODE_KEY, DRAWMODECOUNT).toInt(); if(draw_mode >= DRAWMODECOUNT) { draw_mode = shaded; } - canvas->set_drawMode(draw_mode); - QAction* (dm_acts[]) = {shaded_action, wireframe_action, surfaceangle_action}; + QAction* (dm_acts[]) = {shaded_action, wireframe_action, surfaceangle_action, meshlight_action}; dm_acts[draw_mode]->setChecked(true); + on_drawMode(dm_acts[draw_mode]); resize(600, 400); restoreGeometry(settings.value(WINDOW_GEOM_KEY).toByteArray()); } +void Window::on_drawModePrefs() { + // For now only one draw mode has settings + // when settings for other draw mode will be available + // we will need to check the current mode + if (meshlightprefs->isVisible()) { + meshlightprefs->hide(); + } else { + meshlightprefs->show(); + } +} + void Window::on_open() { - QString filename = QFileDialog::getOpenFileName( - this, "Load .stl file", QString(), "STL files (*.stl, *.STL)"); + const QString filename = QFileDialog::getOpenFileName( + this, "Load .stl file", QString(), "STL files (*.stl *.STL)"); if (!filename.isNull()) { load_stl(filename); } } +void Window::on_open_external() const +{ + if (current_file.isEmpty()) + { + return; + } + + + QString program = open_external_action->data().toString(); + if (program.isEmpty()) { + program = QFileDialog::getOpenFileName((QWidget*) this, "Select program to open with", QDir::rootPath()); + if (!program.isEmpty()) { + QSettings settings; + settings.setValue(OPEN_EXTERNAL_KEY, program); + QString displayName = program.mid(program.lastIndexOf(QDir::separator()) + 1); + open_external_action->setText("Open with " + displayName); + open_external_action->setData(program); + } + } + + QProcess::startDetached(program, QStringList(current_file)); +} + void Window::on_about() { QMessageBox::about(this, "", @@ -195,7 +316,7 @@ void Window::on_about() "

A fast viewer for .stl files.
" "https://github.com/fstl-app/fstl

" - "

© 2014-2022 Matthew Keeter
" + "

© 2014-2024 Matthew Keeter
" "matt.j.keeter@gmail.com

"); } @@ -270,19 +391,30 @@ void Window::on_projection(QAction* proj) void Window::on_drawMode(QAction* act) { + // On mode change hide prefs first + meshlightprefs->hide(); + DrawMode mode; if (act == shaded_action) { + drawModePrefs_action->setEnabled(false); mode = shaded; } else if (act == wireframe_action) { + drawModePrefs_action->setEnabled(false); mode = wireframe; } - else + else if (act == surfaceangle_action) { + drawModePrefs_action->setEnabled(false); mode = surfaceangle; } + else if (act == meshlight_action) + { + drawModePrefs_action->setEnabled(true); + mode = meshlight; + } canvas->set_drawMode(mode); QSettings().setValue(DRAW_MODE_KEY, mode); } @@ -299,6 +431,11 @@ void Window::on_invertZoom(bool d) QSettings().setValue(INVERT_ZOOM_KEY, d); } +void Window::on_resetTransformOnLoad(bool d) { + canvas->setResetTransformOnLoad(d); + QSettings().setValue(RESET_TRANSFORM_ON_LOAD_KEY, d); +} + void Window::on_watched_change(const QString& filename) { if (autoreload_action->isChecked()) @@ -410,6 +547,18 @@ void Window::on_reload() } } +void Window::on_common_view_change(QAction* common) +{ + if (common == common_view_center_action) canvas->common_view_change(centerview); + if (common == common_view_iso_action) canvas->common_view_change(isoview); + if (common == common_view_top_action) canvas->common_view_change(topview); + if (common == common_view_bottom_action) canvas->common_view_change(bottomview); + if (common == common_view_left_action) canvas->common_view_change(leftview); + if (common == common_view_right_action) canvas->common_view_change(rightview); + if (common == common_view_front_action) canvas->common_view_change(frontview); + if (common == common_view_back_action) canvas->common_view_change(backview); +} + bool Window::load_stl(const QString& filename, bool is_reload) { if (!open_action->isEnabled()) return false; @@ -610,3 +759,11 @@ void Window::keyPressEvent(QKeyEvent* event) QMainWindow::keyPressEvent(event); } + +void Window::on_fullscreen() { + if (!this->isFullScreen()) { + this->showFullScreen(); + } else { + this->showNormal(); + } +} diff --git a/src/window.h b/src/window.h index 81cd29f..f13137b 100644 --- a/src/window.h +++ b/src/window.h @@ -7,6 +7,7 @@ #include class Canvas; +class ShaderLightPrefs; class Window : public QMainWindow { @@ -26,6 +27,7 @@ protected: public slots: void on_open(); + void on_open_external() const; void on_about(); void on_bad_stl(); void on_empty_mesh(); @@ -41,14 +43,18 @@ private slots: void on_drawMode(QAction* mode); void on_drawAxes(bool d); void on_invertZoom(bool d); + void on_resetTransformOnLoad(bool d); void on_watched_change(const QString& filename); void on_reload(); + void on_common_view_change(QAction* common); void on_autoreload_triggered(bool r); void on_clear_recent(); void on_load_recent(QAction* a); void on_loaded(const QString& filename); void on_save_screenshot(); + void on_fullscreen(); void on_hide_menuBar(); + void on_drawModePrefs(); private: void rebuild_recent_files(); @@ -58,24 +64,38 @@ private: QPair get_file_neighbors(); QAction* const open_action; + QAction* const open_external_action; QAction* const about_action; QAction* const quit_action; QAction* const perspective_action; + QAction* const common_view_center_action; + QAction* const common_view_iso_action; + QAction* const common_view_top_action; + QAction* const common_view_bottom_action; + QAction* const common_view_left_action; + QAction* const common_view_right_action; + QAction* const common_view_front_action; + QAction* const common_view_back_action; QAction* const orthographic_action; QAction* const shaded_action; QAction* const wireframe_action; QAction* const surfaceangle_action; + QAction* const meshlight_action; + QAction* const drawModePrefs_action; QAction* const axes_action; QAction* const invert_zoom_action; QAction* const reload_action; QAction* const autoreload_action; QAction* const save_screenshot_action; QAction* const hide_menuBar_action; + QAction* const fullscreen_action; + QAction* const resetTransformOnLoadAction; QMenu* const recent_files; QActionGroup* const recent_files_group; QAction* const recent_files_clear_action; const static int MAX_RECENT_FILES=8; + static const QString OPEN_EXTERNAL_KEY; const static QString RECENT_FILE_KEY; const static QString INVERT_ZOOM_KEY; const static QString AUTORELOAD_KEY; @@ -83,6 +103,7 @@ private: const static QString PROJECTION_KEY; const static QString DRAW_MODE_KEY; const static QString WINDOW_GEOM_KEY; + const static QString RESET_TRANSFORM_ON_LOAD_KEY; QString current_file; QString lookup_folder; @@ -91,6 +112,8 @@ private: QFileSystemWatcher* watcher; Canvas* canvas; + + ShaderLightPrefs* meshlightprefs; }; #endif // WINDOW_H diff --git a/xdg/README.txt b/xdg/README.txt new file mode 100644 index 0000000..7aad2b0 --- /dev/null +++ b/xdg/README.txt @@ -0,0 +1,23 @@ +Linux : +----------- +desktop file and application icons installation. +This tells the system that fstl knows to open stl files and allow stl to +be launched using windows key. + +Install : +./xdg_install.sh fstl + +Uninstall : +./xdg_uninstall.sh fstl + +if runned as regular user this will install locally in : + $HOME/.local/share/mime/ + $HOME/.local/share/applications/ + $HOME/.local/share/icons/ + +if runned as root this will install system-wide in : + /usr/share/mime + /usr/share/applications + /usr/share/icons + +Third script xdg_package_install.sh is to be used when building deb or rpm package. diff --git a/xdg/fstlapp-fstl.desktop b/xdg/fstlapp-fstl.desktop new file mode 100644 index 0000000..b4e93c5 --- /dev/null +++ b/xdg/fstlapp-fstl.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=fstl +GenericName=Fast STL Viewer +Exec=fstl %U +Terminal=false +Icon=fstlapp-fstl +Type=Application +MimeType=model/stl; +Categories=Utility; diff --git a/xdg/icons/fstlapp-fstl_128x128.png b/xdg/icons/fstlapp-fstl_128x128.png new file mode 100644 index 0000000..0c31200 Binary files /dev/null and b/xdg/icons/fstlapp-fstl_128x128.png differ diff --git a/xdg/icons/fstlapp-fstl_16x16.png b/xdg/icons/fstlapp-fstl_16x16.png new file mode 100644 index 0000000..d53992e Binary files /dev/null and b/xdg/icons/fstlapp-fstl_16x16.png differ diff --git a/xdg/icons/fstlapp-fstl_22x22.png b/xdg/icons/fstlapp-fstl_22x22.png new file mode 100644 index 0000000..40e760e Binary files /dev/null and b/xdg/icons/fstlapp-fstl_22x22.png differ diff --git a/xdg/icons/fstlapp-fstl_256x256.png b/xdg/icons/fstlapp-fstl_256x256.png new file mode 100644 index 0000000..4235dc5 Binary files /dev/null and b/xdg/icons/fstlapp-fstl_256x256.png differ diff --git a/xdg/icons/fstlapp-fstl_32x32.png b/xdg/icons/fstlapp-fstl_32x32.png new file mode 100644 index 0000000..8bab67e Binary files /dev/null and b/xdg/icons/fstlapp-fstl_32x32.png differ diff --git a/xdg/icons/fstlapp-fstl_48x48.png b/xdg/icons/fstlapp-fstl_48x48.png new file mode 100644 index 0000000..851d8bd Binary files /dev/null and b/xdg/icons/fstlapp-fstl_48x48.png differ diff --git a/xdg/icons/fstlapp-fstl_64x64.png b/xdg/icons/fstlapp-fstl_64x64.png new file mode 100644 index 0000000..0f83e6b Binary files /dev/null and b/xdg/icons/fstlapp-fstl_64x64.png differ diff --git a/xdg/xdg_install.sh b/xdg/xdg_install.sh new file mode 100755 index 0000000..b9d59b2 --- /dev/null +++ b/xdg/xdg_install.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# This script will install mimetypes, icons and desktop file, +# it takes a name in argument +# +# if runned as regular user this will install locally in : +# $HOME/.local/share/mime/ +# $HOME/.local/share/applications/ +# $HOME/.local/share/icons/ +# +# if runned as root this will install system-wide in : +# /usr/share/mime +# /usr/share/applications +# /usr/share/icons + +if [ $# != 1 ]; then + echo "You must provide an application name" + exit 1 +fi + +name=$1 + +# echo "Installing mimetypes" +# xdg-mime install fstlapp-$name-mimetypes.xml + +echo "Installing desktop file" +xdg-desktop-menu install fstlapp-$name.desktop + +echo "Installing apps icons" +iclist="fstlapp-$name" +for im in $iclist +do + xdg-icon-resource install --theme hicolor --context apps --size 16 icons/${im}_16x16.png $im + xdg-icon-resource install --theme hicolor --context apps --size 22 icons/${im}_22x22.png $im + xdg-icon-resource install --theme hicolor --context apps --size 32 icons/${im}_32x32.png $im + xdg-icon-resource install --theme hicolor --context apps --size 48 icons/${im}_48x48.png $im + xdg-icon-resource install --theme hicolor --context apps --size 64 icons/${im}_64x64.png $im + xdg-icon-resource install --theme hicolor --context apps --size 128 icons/${im}_128x128.png $im + xdg-icon-resource install --theme hicolor --context apps --size 256 icons/${im}_256x256.png $im +done + +# echo "Installing mimetypes icons" +# iclist="`cat fstlapp-$name-mimetypes.xml | grep "icon name" | sed 's/^.*"\(.*\)".*$/\1/'`" +# for im in $iclist +# do +# xdg-icon-resource install --theme hicolor --context mimetypes --size 16 icons/${im}_16x16.png $im +# xdg-icon-resource install --theme hicolor --context mimetypes --size 22 icons/${im}_22x22.png $im +# xdg-icon-resource install --theme hicolor --context mimetypes --size 32 icons/${im}_32x32.png $im +# xdg-icon-resource install --theme hicolor --context mimetypes --size 48 icons/${im}_48x48.png $im +# xdg-icon-resource install --theme hicolor --context mimetypes --size 64 icons/${im}_64x64.png $im +# done + diff --git a/xdg/xdg_package_install.sh b/xdg/xdg_package_install.sh new file mode 100755 index 0000000..7e19a42 --- /dev/null +++ b/xdg/xdg_package_install.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# For a package installation (rpm or deb), we must proceed a different way +# This script takes two arguments, the first one is the installation +# prefix and the second is the name + +if [ $# != 2 ]; then + echo "You must provide two arguments" + exit 1 +fi + +base=$1 +name=$2 + +# echo "Drop mimetypes file in /usr/share/mime/packages/" +# mkdir -p $base/usr/share/mime/packages/ +# cp fstlapp-$name-mimetypes.xml $base/usr/share/mime/packages/ + +echo "Drop desktop file in /usr/share/applications/" +mkdir -p $base/usr/share/applications/ +cp fstlapp-$name.desktop $base/usr/share/applications/ + +slist="16 22 32 48 64 128 256" +echo "Installing apps icons" +iclist="fstlapp-$name" +for im in $iclist +do + for s in $slist + do + mkdir -p $base/usr/share/icons/hicolor/${s}x${s}/apps + cp icons/${im}_${s}x${s}.png $base/usr/share/icons/hicolor/${s}x${s}/apps/$im.png + done +done + +# echo "Installing mimetypes icons" +# iclist="`cat fstlapp-$name-mimetypes.xml | grep "icon name" | sed 's/^.*"\(.*\)".*$/\1/'`" +# for im in $iclist +# do +# for s in $slist +# do +# mkdir -p $base/usr/share/icons/hicolor/${s}x${s}/mimetypes +# cp icons/${im}_${s}x${s}.png $base/usr/share/icons/hicolor/${s}x${s}/mimetypes/$im.png +# done +# done + +# +# Put this in the post installation and post uninstallation scripts +# +#echo "Updating mime database" +#update-mime-database /usr/share/mim +# +#echo "Updating desktop database" +#update-desktop-database diff --git a/xdg/xdg_uninstall.sh b/xdg/xdg_uninstall.sh new file mode 100755 index 0000000..1dd7ef4 --- /dev/null +++ b/xdg/xdg_uninstall.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# This script will uninstall mimetypes, icons and desktop file +# +# if runned as regular user this will uninstall locally from : +# $HOME/.local/share/mime/ +# $HOME/.local/share/applications/ +# $HOME/.local/share/icons/ +# +# if runned as root this will uninstall system-wide from : +# /usr/share/mime +# /usr/share/applications +# /usr/share/icons + +if [ $# != 1 ]; then + echo "You must provide a name" + exit 1 +fi + +name=$1 + +# echo "Uninstalling mimetypes" +# xdg-mime uninstall fstlapp-$name-mimetypes.xml + +echo "Uninstalling desktop file" +xdg-desktop-menu uninstall fstlapp-$name.desktop + +echo "Uninstalling apps icons" +iclist="fstlapp-$name" +for im in $iclist +do + xdg-icon-resource uninstall --theme hicolor --context apps --size 16 $im + xdg-icon-resource uninstall --theme hicolor --context apps --size 22 $im + xdg-icon-resource uninstall --theme hicolor --context apps --size 32 $im + xdg-icon-resource uninstall --theme hicolor --context apps --size 48 $im + xdg-icon-resource uninstall --theme hicolor --context apps --size 64 $im + xdg-icon-resource uninstall --theme hicolor --context apps --size 128 $im + xdg-icon-resource uninstall --theme hicolor --context apps --size 256 $im +done + +# echo "Uninstalling mimetypes icons" +# iclist="`cat fstlapp-$name-mimetypes.xml | grep "icon name" | sed 's/^.*"\(.*\)".*$/\1/'`" +# for im in $iclist +# do +# xdg-icon-resource uninstall --theme hicolor --context mimetypes --size 16 $im +# xdg-icon-resource uninstall --theme hicolor --context mimetypes --size 22 $im +# xdg-icon-resource uninstall --theme hicolor --context mimetypes --size 32 $im +# xdg-icon-resource uninstall --theme hicolor --context mimetypes --size 48 $im +# xdg-icon-resource uninstall --theme hicolor --context mimetypes --size 64 $im +# done