Mon, 06 May 2013 03:31:03 +0300
Begin work on external program support (Ytruder partially supported)
extprogs.cpp | file | annotate | diff | comparison | revisions | |
extprogs.h | file | annotate | diff | comparison | revisions | |
gui.cpp | file | annotate | diff | comparison | revisions | |
gui.h | file | annotate | diff | comparison | revisions | |
gui_editactions.cpp | file | annotate | diff | comparison | revisions | |
ldforge.pro | file | annotate | diff | comparison | revisions | |
misc.h | file | annotate | diff | comparison | revisions | |
zz_configDialog.cpp | file | annotate | diff | comparison | revisions | |
zz_configDialog.h | file | annotate | diff | comparison | revisions |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extprogs.cpp Mon May 06 03:31:03 2013 +0300 @@ -0,0 +1,151 @@ +#include "common.h" +#include "config.h" +#include "misc.h" +#include "extprogs.h" +#include "gui.h" +#include "file.h" +#include <qprocess.h> +#include <qtemporaryfile.h> +#include <qeventloop.h> + +// ============================================================================= +cfg (str, prog_isecalc, ""); +cfg (str, prog_intersector, ""); +cfg (str, prog_coverer, ""); +cfg (str, prog_ytruder, ""); +cfg (str, prog_datheader, ""); + +strconfig* g_extProgPaths[] = { + &prog_isecalc, + &prog_intersector, + &prog_coverer, + &prog_ytruder, + &prog_datheader, +}; + +const char* g_extProgNames[] = { + "Isecalc", + "Intersector", + "Coverer", + "Ytruder", + "DATHeader", +}; + +// ============================================================================= +static void noPathConfigured (const extprog prog) { + const char* name = g_extProgNames[prog]; + + critical (fmt ("Couldn't run %s as no path has " + "been defined for it. Use the configuration dialog's External Programs " + "tab to define a path for %s.", name, name)); +} + +// ============================================================================= +static void processError (const extprog prog, QProcess& proc) { + const char* name = g_extProgNames[prog]; + str errmsg; + + switch (proc.error ()) { + case QProcess::FailedToStart: + errmsg = fmt ("Failed to launch %s. Check that you have set the proper path " + "to %s and that you have the proper permissions to launch it.", name, name); + break; + + case QProcess::Crashed: + errmsg = fmt ("%s crashed.", name); + break; + + case QProcess::WriteError: + case QProcess::ReadError: + errmsg = fmt ("I/O error while interacting with %s.", name); + break; + + case QProcess::UnknownError: + errmsg = fmt ("Unknown error occurred while executing %s.", name); + break; + + case QProcess::Timedout: + errmsg = fmt ("%s timed out.", name); + break; + } + + critical (errmsg); +} + +// ============================================================================= +static bool mkTempFile (QTemporaryFile& tmp, str& fname) { + if (!tmp.open ()) + return false; + + fname = tmp.fileName (); + tmp.close (); + return true; +} + +bool g_processDone = false; + +// ============================================================================= +void runYtruder () { + if (prog_ytruder.value.len () == 0) { + noPathConfigured (Ytruder); + return; + } + + QTemporaryFile in, out, input; + str inname, outname, inputname; + FILE* fp; + + if (!mkTempFile (in, inname) || !mkTempFile (out, outname) || !mkTempFile (input, inputname)) + return; + + QProcess proc; + QStringList argv ({"-p", "0", "-y", inname, outname}); + + // Write the input file + fp = fopen (inname, "w"); + if (!fp) + return; + + for (LDObject* obj : g_win->sel ()) { + str line = fmt ("%s\r\n", obj->getContents ().chars ()); + fwrite (line.chars(), 1, ~line, fp); + } + fclose (fp); + + // Init stdin + FILE* stdinfp = fopen (inputname, "w"); + + // Begin! + proc.setStandardInputFile (inputname); + proc.setStandardOutputFile ("blarg"); + proc.start (prog_ytruder.value, argv); + + // Write an enter - one is expected + char enter[2] = "\n"; + enter[1] = '\0'; + fwrite (enter, 1, sizeof enter, stdinfp); + fflush (stdinfp); + + // Wait while it runs + proc.waitForFinished (); + + if (proc.exitStatus () == QProcess::CrashExit) { + processError (Ytruder, proc); + return; + } + + // Read the output file + fp = fopen (outname, "r"); + if (!fp) + fprintf (stderr, "couldn't read %s\n", outname.chars ()); + + char line[1024]; + while (fgets (line, sizeof line, fp)) { + printf ("%s", line); + LDObject* obj = parseLine (str (line).strip ({'\n', '\r'})); + g_curfile->addObject (obj); + } + fclose (fp); + + g_win->refresh (); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extprogs.h Mon May 06 03:31:03 2013 +0300 @@ -0,0 +1,39 @@ +#ifndef EXTPROGS_H +#define EXTPROGS_H + +#include <qobject.h> + +class QProcess; +class ProcessWaiter : public QObject { + Q_OBJECT + +public: + ProcessWaiter (QProcess* proc, bool& readyvar) : m_proc (proc), m_readyvar (readyvar) { + m_readyvar = false; + } + + int exitFlag () { return m_exitflag; } + +public slots: + void slot_procDone (int exitflag) { + m_readyvar = true; + m_exitflag = exitflag; + } + +private: + QProcess* m_proc; + bool& m_readyvar; + int m_exitflag; +}; + +enum extprog { + IseCalc, + Intersector, + Coverer, + Ytruder, + DATHeader +}; + +void runYtruder (); + +#endif // EXTPROGS_H \ No newline at end of file
--- a/gui.cpp Mon May 06 00:10:56 2013 +0300 +++ b/gui.cpp Mon May 06 03:31:03 2013 +0300 @@ -375,7 +375,7 @@ addToolBarAction ("roundCoords"); addToolBarAction ("screencap"); addToolBarAction ("uncolorize"); - + addToolBarAction ("extrude"); updateToolBars (); }
--- a/gui.h Mon May 06 00:10:56 2013 +0300 +++ b/gui.h Mon May 06 03:31:03 2013 +0300 @@ -27,6 +27,8 @@ #include <QTextEdit> #include <qpushbutton.h> #include <qlistwidget.h> +#include <qlabel.h> +#include <qboxlayout.h> #include "gldraw.h" #include "config.h" @@ -183,6 +185,37 @@ void slot_lastSecondCleanup (); }; +// ============================================================================= +// LabeledWidget +// +// Convenience class for a widget with a label beside it. +// ============================================================================= +template<class R> class LabeledWidget : public QWidget { +public: + LabeledWidget (const char* labelstr, QWidget* parent) : QWidget (parent) { + m_widget = new R (this); + m_label = new QLabel (labelstr, this); + + m_layout = new QHBoxLayout; + m_layout->addWidget (m_label); + m_layout->addWidget (m_widget); + setLayout (m_layout); + } + + R* widget () const { return m_widget; } + R* w () const { return m_widget; } + QLabel* label () const { return m_label; } + QLabel* l () const { return m_label; } + void setWidget (R* widget) { m_widget = widget; } + void setLabel (QLabel* label) { m_label = label; } + operator R* () { return m_widget; } + +private: + R* m_widget; + QLabel* m_label; + QHBoxLayout* m_layout; +}; + // ----------------------------------------------------------------------------- // Other GUI-related stuff not directly part of ForgeWindow: QPixmap getIcon (const char* sIconName);
--- a/gui_editactions.cpp Mon May 06 00:10:56 2013 +0300 +++ b/gui_editactions.cpp Mon May 06 03:31:03 2013 +0300 @@ -25,6 +25,10 @@ #include "zz_setContentsDialog.h" #include "misc.h" #include "bbox.h" +#include "radiobox.h" +#include "extprogs.h" +#include <qspinbox.h> +#include <qcheckbox.h> vector<LDObject*> g_Clipboard; @@ -680,4 +684,43 @@ History::addEntry (new EditHistory (indices, oldCopies, newCopies)); g_win->refresh (); } +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +MAKE_ACTION (extrude, "Extrude", "extrude", "Extrude selected lines to a given plane", KEY (F8)) { + QDialog* dlg = new QDialog (g_win); + + RadioBox* rb_mode = new RadioBox ("Extrusion mode", {"Project", "Mirror"}, 0, Qt::Horizontal, dlg); + RadioBox* rb_axis = new RadioBox ("Axis", {"X", "Y", "Z"}, 0, Qt::Horizontal, dlg); + LabeledWidget<QDoubleSpinBox>* dsb_depth = new LabeledWidget<QDoubleSpinBox> ("Plane depth", dlg); + QDialogButtonBox* bbx_buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + QCheckBox* cb_edges = new QCheckBox ("Add edgelines to extrusion point"); + + QWidget::connect (bbx_buttons, SIGNAL (accepted ()), dlg, SLOT (accept ())); + QWidget::connect (bbx_buttons, SIGNAL (rejected ()), dlg, SLOT (reject ())); + + dsb_depth->w ()->setMinimum (-10000.0); + dsb_depth->w ()->setMaximum (10000.0); + dsb_depth->w ()->setDecimals (3); + + QVBoxLayout* layout = new QVBoxLayout (dlg); + layout->addWidget (rb_mode); + layout->addWidget (rb_axis); + layout->addWidget (dsb_depth); + layout->addWidget (cb_edges); + layout->addWidget (bbx_buttons); + + dlg->setWindowIcon (getIcon ("extrude")); + + if (!dlg->exec ()) + return; + + const double depth = dsb_depth->w ()->value (); + const Axis axis = (Axis) rb_axis->value (); + const enum modetype { Projection, Mirror } mode = (modetype) rb_mode->value (); + const bool addEdges = cb_edges->isChecked (); + + runYtruder (); } \ No newline at end of file
--- a/ldforge.pro Mon May 06 00:10:56 2013 +0300 +++ b/ldforge.pro Mon May 06 03:31:03 2013 +0300 @@ -15,6 +15,7 @@ colors.h \ common.h \ config.h \ + extprogs.h \ file.h \ gldraw.h \ gui.h \ @@ -33,14 +34,15 @@ zz_setContentsDialog.h SOURCES += bbox.cpp \ + colors.cpp \ config.cpp \ - colors.cpp \ + extprogs.cpp \ + file.cpp \ gldraw.cpp \ gui.cpp \ gui_actions.cpp \ gui_editactions.cpp \ history.cpp \ - file.cpp \ ldtypes.cpp \ main.cpp \ misc.cpp \
--- a/misc.h Mon May 06 00:10:56 2013 +0300 +++ b/misc.h Mon May 06 03:31:03 2013 +0300 @@ -21,6 +21,7 @@ #include "common.h" #include "str.h" +#include "config.h" #define NUM_PRIMES 500 @@ -71,6 +72,7 @@ double snap (double value, const Grid::Config axis); }; +// ============================================================================= template<class T> void dataswap (T& a, T& b) { T c = a; a = b;
--- a/zz_configDialog.cpp Mon May 06 00:10:56 2013 +0300 +++ b/zz_configDialog.cpp Mon May 06 03:31:03 2013 +0300 @@ -314,6 +314,15 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= +void ConfigDialog::initExtProgTab () { + QWidget* tab = new QWidget; + + QGridLayout* layout = new QGridLayout; +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= void ConfigDialog::updateQuickColorList (quickColorMetaEntry* pSel) { for (QListWidgetItem* qItem : quickColorItems) delete qItem;
--- a/zz_configDialog.h Mon May 06 00:10:56 2013 +0300 +++ b/zz_configDialog.h Mon May 06 03:31:03 2013 +0300 @@ -34,7 +34,7 @@ public: QTabWidget* tabs; - QWidget* mainTab, *shortcutsTab, *quickColorTab; + QWidget* mainTab, *shortcutsTab, *quickColorTab, *extProgTab; // ========================================================================= // Main tab widgets @@ -80,6 +80,7 @@ void initShortcutsTab (); void initQuickColorTab (); void initGridTab (); + void initExtProgTab (); void makeSlider (QSlider*& qSlider, short int dMin, short int dMax, short int dDefault); void setButtonBackground (QPushButton* qButton, str zValue);