mini-term in qt4
Tags c++, compiling, computer mad science, qt4
mini-term in qt4.
Today's features:
Screenshot:
http://rainbowsally.org/rainbowsally...iterm-test.png
If you want to try this, be forewarned:
Run
and then
So that all the moc_&.cpp files are created before you 'make' the app itself.
[I won't go into depth on the api thing, but with four parameters Windows gives strong clues as to typing without enforcing overly-strict typing rules. And integer will go into wparam. A pointer or a struct will go into lparam. Messages identify it more completely and tell what to do with it. It's intuitive by nature and one of the few features of Windows that I like better than any linux gui toolkits I've tried so far.]
The self extractor (near the bottom) contains all the files including the Makefile and the mc2.def that created the Makefile but let's take look at the api, which is the layer between our custom code and the Designer-generated gui code.
file: miniterm-test/app-main.cpp
purpose: source file
Take a look at the definition of
in the source above.
The enums are identical to the 'slot' names plus a prefix of 'msg_'.
These slots are never polymorphic, so this is a reliable system for identifying calls and their parameters.
Here are some snips from the header.
There's the enums (above). And here's the class functions from the cpp file (below) and you'll notice that the call types are all the same and the resemblance to the Windows WNDPROC is no accident.
All these 'slots' do is translate from QT slots to generic calls to handler(). As you can see it would be pretty difficult to pass the wrong type of parameter in the wrong parameter position.
Another interesting feature in the app-main.cpp file (i.e. coded independently from the ui code) is its definition of
That code runs every 20 milliseconds by default, but can be set to run slower or faster, either at setup time or when you need the speed.
It's not a message loop. It's better in some ways due to its simplicity.
This code, the application, and the interface to the ui can be used to do software "breadboarding".
Doncha just HATE those sockets tutorials where you have to open two terminals to run the things?
Sockets code can run in these loops. No second thread, no mutex, no timing issues. And no dependency on QT threads, so I'm thinking this will be great for really understanding sockets... when I get those done.
The key to this mutability is in the code here.
where 'run()' is defined as follows.
And that loopFunc is the same loop_func() in the app-main source above. It's the function that curretnly is designed reads input from the text edit widget and decides how to execute it.
Interested? Here's the self extractor.
file: miniterm-test.sfxz
purpose: utility (executable)
Once again, be aware that you have to 'make ui' before you 'make' the application. That's how we keep the sizes reasonable.
Good luck!
PS. If you click on the app it opens in the default directory. And there appears to be some confusion about what that is! PWD says your home dir. Qt or KDE says it's Documents. "cd .." to get to your REAL home dir or add code to make it open where it was clicked on or something.
If you have libLQ and mc2, type 'lq-find appdir' if you want to see some code for opening it in the folder where it was clicked on. (uses getpid() and readlink())
The Computer Mad Science Team
:-)
Today's features:
- A simple terminal-like application built from a qt4 class that can be used for other stuff too.
- The present application can run shell commands and has copy/paste (ctrl-c, ctrl-v) capabilitity.
- Another example of the Windows-like api so that C/C++ code can run in Qt4.
- Runs the custom code (terminal in this case) inside a QT 'exec' loop... sorta. We call it 'run()'.
Screenshot:
http://rainbowsally.org/rainbowsally...iterm-test.png
If you want to try this, be forewarned:
Run
Code:
make ui
Code:
make
[I won't go into depth on the api thing, but with four parameters Windows gives strong clues as to typing without enforcing overly-strict typing rules. And integer will go into wparam. A pointer or a struct will go into lparam. Messages identify it more completely and tell what to do with it. It's intuitive by nature and one of the few features of Windows that I like better than any linux gui toolkits I've tried so far.]
The self extractor (near the bottom) contains all the files including the Makefile and the mc2.def that created the Makefile but let's take look at the api, which is the layer between our custom code and the Designer-generated gui code.
file: miniterm-test/app-main.cpp
purpose: source file
Code:
#include <QtGui/QApplication> #include "lqminiterm.h" #include "ui_lqminiterm.h" #include <ctype.h> // alnum() #include <stdio.h> void dbg(){} static bool cmd_set; static char* cmd; static bool text_mode; static void term_print(lqMiniTerm* term, const char* buf) { text_mode = true; term->ui->plainTextEdit->appendPlainText(buf); text_mode = false; term->ui->plainTextEdit->textCursor().movePosition(QTextCursor::End); term->last_pos = term->ui->plainTextEdit->textCursor().position(); } static void prompt(lqMiniTerm* term) { char buf[256]; sprintf(buf, "%s", getenv("PWD")); int pathlen = strlen(buf); // trim path down to 40 chars if(pathlen > 40) sprintf(buf + 18, "...%s", buf + pathlen - 19); strcat(buf, "$>"); term_print(term, buf); } // user programmable loop func in app-main() // this just does shell commands. void loop_func(lqMiniTerm* term) { // only operates in command mode if(text_mode) return; char* cmdptr = cmd; int slen; if(!cmd_set) return; cmd_set = false; // queue up text while(isspace(*cmdptr)) cmdptr++; if(!*cmdptr) return; //////////////////////////////////////////// // A couple of keywords we handle ourselves // 'cd' <path> | 'exit' char firstword[256]; sscanf(cmdptr, "%s", firstword); if(strcmp(firstword, "cd") == 0) { cmdptr += 3; while(isspace(*cmdptr)) cmdptr++; char* cwd; chdir(cmdptr); cwd = getcwd(0, 0); setenv("PWD", cwd, true); free(cwd); prompt(term); return; } else if(strcmp(firstword, "exit") == 0) { term->onClose(); } //////////////////////////////////////// // piped shell command char* buf = (char*)malloc(256); size_t bufsize = 256; sprintf(buf, "%s 2>&1", cmdptr); FILE* p = popen(buf, "r"); while(!feof(p)) { *buf = 0; getline(&buf, &bufsize, p); slen = strlen(buf); if(!slen) break; buf[slen-1] = 0; term_print(term, buf); } fclose(p); free(buf); prompt(term); } #define UNUSED(x) x=x void handler(lqMiniTerm* hwnd, uint msg, long wparam, void* lparam) { UNUSED(lparam); switch(msg) { case msg_init: text_mode = false; break; case msg_onClose: // printf("Handled: Closing\n"); hwnd->hide(); // signal to runner we can quit hwnd->close(); break; case msg_onNewline: { // to get the newly entered text we take the text edit's buffer // from last_pos to cur_pos and update last_pos in the class int last_pos = hwnd->last_pos; int cur_pos = hwnd->ui->plainTextEdit->textCursor().position(); if(!text_mode && (cur_pos >= last_pos)) { QString str = hwnd->ui->plainTextEdit->document()->toPlainText(); const char* s = str.right(cur_pos - last_pos); int len = strlen(s); if(len && !cmd_set) { cmd = (char*)realloc(cmd, len); memcpy(cmd, s, len); cmd[len-1] = 0; cmd_set = true; printf("Text: %s\n", cmd); } } // and... only if cur_pos > last_pos hwnd->last_pos = cur_pos; // printf("Handled: Newline, block = %d\n", (int)wparam); break; } case msg_onCursorPositionChanged: { // printf("Handled: Cursor Position: pos=%d\n",(int)wparam); int new_pos = (int)wparam; if(new_pos < hwnd->last_pos) hwnd->ui->plainTextEdit->setReadOnly(true); else hwnd->ui->plainTextEdit->setReadOnly(false); break; } } } int main(int argc, char *argv[]) { dbg(); // this sets the global qApp instance new QApplication (argc, argv); lqMiniTerm w(loop_func, handler); w.show(); prompt(&w); // return qApp->exec(); return w.run(); }
Code:
void handler(lqMiniTerm* hwnd, uint msg, long wparam, void* lparam)
The enums are identical to the 'slot' names plus a prefix of 'msg_'.
These slots are never polymorphic, so this is a reliable system for identifying calls and their parameters.
Here are some snips from the header.
Code:
enum{ msg_init = 0, // 0 (obj,0,0,0) msg_onClose, // 1 (obj,1,0,0) msg_onNewline, // 2 (obj,2,0,0) msg_onCursorPositionChanged // 3 (obj,3,int,0) };
Code:
void lqMiniTerm::onClose() { handler(this, msg_onClose, 0, 0); } void lqMiniTerm::onNewline(int argA) { handler(this, msg_onNewline, argA, 0); } void lqMiniTerm::onCursorPositionChanged() { QTextCursor cursor = ui->plainTextEdit->textCursor(); int pos = cursor.position(); handler(this, msg_onCursorPositionChanged, pos, 0); } void lqMiniTerm::init() { handler(this, msg_init, 0, 0); }
Another interesting feature in the app-main.cpp file (i.e. coded independently from the ui code) is its definition of
Code:
void loop_func(lqMiniTerm* term)
It's not a message loop. It's better in some ways due to its simplicity.
This code, the application, and the interface to the ui can be used to do software "breadboarding".
Doncha just HATE those sockets tutorials where you have to open two terminals to run the things?
Sockets code can run in these loops. No second thread, no mutex, no timing issues. And no dependency on QT threads, so I'm thinking this will be great for really understanding sockets... when I get those done.
The key to this mutability is in the code here.
Code:
// return qApp->exec(); return w.run();
Code:
int lqMiniTerm::run() { for(;;) { qApp->processEvents(); if(!isVisible()) break; loopFunc(this); usleep(loop_timeout * 1000); } return 0; }
Interested? Here's the self extractor.
file: miniterm-test.sfxz
purpose: utility (executable)
Code:
#!/bin/sh # base64 self extractor # file: miniterm-test filename=miniterm-test # don't allow user to click on the file if ! tty >/dev/null; then xmessage -center " $(basename $0) must be run in a terminal " exit fi # create and/or clear out tmp dir mkdir -p $HOME/tmp/sfxz rm -rf $HOME/tmp/sfxz/* base64 -d << _BEOF >$HOME/tmp/sfxz/$filename.xz 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 _BEOF (cd $HOME/tmp/sfxz && tar -xaf miniterm-test.xz) rm -f $HOME/tmp/sfxz/miniterm-test.xz cat << _BEOF > $HOME/tmp/sfxz/post-extract #!/bin/sh is_yes() # returns OK if first char is Y or y { local key=`echo $1 | cut -b1 | sed 's/y/Y/; /Y/!d'` [ "$key" == 'Y' ] && return 0 # true return 1 # false } if [ -e miniterm-test ]; then printf " Overwrite existing file(s)? [N/y]:" read key if ! is_yes $key ;then echo "Aborting.." exit 0 fi fi mv $HOME/tmp/sfxz/miniterm-test . _BEOF sh $HOME/tmp/sfxz/post-extract rm -rf $HOME/tmp/sfxz/* rmdir $HOME/tmp/sfxz 2>/dev/null || true rmdir $HOME/tmp 2>/dev/null || true
Good luck!
PS. If you click on the app it opens in the default directory. And there appears to be some confusion about what that is! PWD says your home dir. Qt or KDE says it's Documents. "cd .." to get to your REAL home dir or add code to make it open where it was clicked on or something.
If you have libLQ and mc2, type 'lq-find appdir' if you want to see some code for opening it in the folder where it was clicked on. (uses getpid() and readlink())
The Computer Mad Science Team
:-)
Total Comments 0