1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, The Regents of the University of California
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #pragma once
34 
35 #include <tcl.h>
36 
37 #include <QDockWidget>
38 #include <QPushButton>
39 #include <QSettings>
40 #include <QStringList>
41 #include <QTextEdit>
42 
43 #include "tclCmdInputWidget.h"
44 
45 namespace odb {
46 class dbDatabase;
47 }
48 
49 namespace utl {
50 class Logger;
51 }
52 
53 namespace gui {
54 
55 // This shows a line edit to enter tcl commands and a
56 // text area that is used to show the commands and their
57 // results.  A command history is maintained and stored in
58 // settings across runs.  Up/down arrows scroll through the
59 // history as usual.  Qt itself provides editing features
60 // within the line edit.
61 class ScriptWidget : public QDockWidget
62 {
63   Q_OBJECT
64 
65  public:
66   ScriptWidget(QWidget* parent = nullptr);
67   ~ScriptWidget();
68 
69   void readSettings(QSettings* settings);
70   void writeSettings(QSettings* settings);
71 
72   void setLogger(utl::Logger* logger);
73 
74   void setFont(const QFont& font);
75 
76  signals:
77   // Commands might have effects that others need to know
78   // (eg change placement of an instance requires a redraw)
79   void commandExecuted(int return_code);
80   // tcl exit has been initiated, want the gui to handle
81   // shutdown
82   void tclExiting();
83 
84  private slots:
85   // Triggered when the user hits return in the line edit
86   void executeCommand();
87 
88   void outputChanged();
89 
90   void pause();
91 
92   void pauserClicked();
93 
94   void goBackHistory();
95   void goForwardHistory();
96 
97  protected:
98   // required to ensure input command space it set to correct height
99   void resizeEvent(QResizeEvent* event) override;
100 
101  private:
102   void setupTcl();
103 
104   void addToOutput(const QString& text, const QColor& color);
105   void addCommandToOutput(const QString& cmd);
106   void addTclResultToOutput(int return_code);
107   void addReportToOutput(const QString& text);
108   void addLogToOutput(const QString& text, const QColor& color);
109 
110   static int channelOutput(ClientData instanceData,
111                            const char* buf,
112                            int toWrite,
113                            int* errorCodePtr);
114   static int tclExitHandler(ClientData instance_data,
115                             Tcl_Interp *interp,
116                             int argc,
117                             const char **argv);
118 
119   QTextEdit* output_;
120   TclCmdInputWidget* input_;
121   QPushButton* pauser_;
122   Tcl_Interp* interp_;
123   QStringList history_;
124   QString history_buffer_last_;
125   int historyPosition_;
126   bool paused_;
127   utl::Logger* logger_;
128 
129   // Logger sink
130   template <typename Mutex>
131   class GuiSink;
132 
133   static Tcl_ChannelType stdout_channel_type_;
134 
135   // maximum number of character to display in a log line
136   const int max_output_line_length_ = 1000;
137 
138   const QColor cmd_msg_        = Qt::black;
139   const QColor tcl_error_msg_  = Qt::red;
140   const QColor tcl_ok_msg_     = Qt::blue;
141   const QColor buffer_msg_     = QColor(0x30, 0x30, 0x30);
142 };
143 
144 }  // namespace gui
145