wip
This commit is contained in:
BIN
system/clearpilot/tools/qt_shell
Executable file
BIN
system/clearpilot/tools/qt_shell
Executable file
Binary file not shown.
76
system/clearpilot/tools/qt_shell.cc
Normal file
76
system/clearpilot/tools/qt_shell.cc
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
#include <QTextEdit>
|
||||
#include <QProcess>
|
||||
#include <QVBoxLayout>
|
||||
#include <QFont>
|
||||
#include <QScreen>
|
||||
#include <QScrollBar>
|
||||
#include <QGuiApplication>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#include <wayland-client-protocol.h>
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s '<command>'\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
QWidget window;
|
||||
window.setWindowTitle("Shell Command Output Viewer");
|
||||
window.setStyleSheet("background-color: black;");
|
||||
window.showFullScreen();
|
||||
|
||||
auto windowHandle = window.windowHandle();
|
||||
if (!windowHandle) {
|
||||
fprintf(stderr, "Error: Unable to obtain window handle.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
|
||||
auto *s = static_cast<wl_surface*>(native->nativeResourceForWindow("surface", windowHandle));
|
||||
if (!s) {
|
||||
fprintf(stderr, "Error: Unable to obtain native Wayland surface.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270);
|
||||
wl_surface_commit(s);
|
||||
|
||||
window.setFixedSize(2160, 1080);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(&window);
|
||||
QTextEdit *outputDisplay = new QTextEdit;
|
||||
outputDisplay->setFont(QFont("Consolas", 32));
|
||||
outputDisplay->setReadOnly(true);
|
||||
outputDisplay->setFixedSize(2160, 1080);
|
||||
outputDisplay->setStyleSheet("color: white; background-color: black;");
|
||||
outputDisplay->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Hide the vertical scrollbar
|
||||
|
||||
layout->addWidget(outputDisplay);
|
||||
|
||||
QProcess process;
|
||||
QObject::connect(&process, &QProcess::readyReadStandardOutput, [&]() {
|
||||
static QStringList lines;
|
||||
QString output = process.readAllStandardOutput();
|
||||
lines += output.split("\n", QString::SkipEmptyParts);
|
||||
while (lines.size() > 100) {
|
||||
lines.removeFirst();
|
||||
}
|
||||
outputDisplay->setPlainText(lines.join("\n"));
|
||||
outputDisplay->verticalScrollBar()->setValue(outputDisplay->verticalScrollBar()->maximum());
|
||||
});
|
||||
|
||||
QObject::connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [&]() {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
QString command = argv[1];
|
||||
process.start(QString("bash -c \"%1\"").arg(command));
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
sudo su comma -c "python3 shell.py \"echo hello; sleep 5\"
|
||||
sudo su comma -c "python3 /data/openpilot/system/clearpilot/tools/shell.py \"echo hello; sleep 5\"
|
||||
|
||||
785
system/clearpilot/tools_wip_4_28/QConsole.cc
Normal file
785
system/clearpilot/tools_wip_4_28/QConsole.cc
Normal file
@@ -0,0 +1,785 @@
|
||||
/**
|
||||
Change log:
|
||||
(C) 2005 by Houssem BDIOUI <houssem.bdioui@gmail.com>
|
||||
(C) 2010 by YoungTaek Oh. (migrated to Qt4)
|
||||
(C) 2014-2015 Igor Malinovskiy
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
*/
|
||||
|
||||
// #include "qconsole.h"
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QDebug>
|
||||
#include <QVBoxLayout>
|
||||
#include <QApplication>
|
||||
#include <QScrollBar>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
//#define USE_POPUP_COMPLETER
|
||||
#define WRITE_ONLY QIODevice::WriteOnly
|
||||
|
||||
QSize PopupListWidget::sizeHint() const
|
||||
{
|
||||
QAbstractItemModel *model = this->model();
|
||||
QAbstractItemDelegate *delegate = this->itemDelegate();
|
||||
const QStyleOptionViewItem sovi;
|
||||
int left, top, right, bottom = 0;
|
||||
|
||||
QMargins margin = this->contentsMargins();
|
||||
|
||||
top = margin.top();
|
||||
bottom = margin.bottom();
|
||||
left = margin.left();
|
||||
right = margin.right();
|
||||
|
||||
const int vOffset = top + bottom;
|
||||
const int hOffset = left + right;
|
||||
|
||||
bool vScrollOn = false;
|
||||
int height = 0;
|
||||
int width = 0;
|
||||
for (int i=0; i<this->count(); ++i) {
|
||||
QModelIndex index = model->index(i, 0);
|
||||
QSize itemSizeHint = delegate->sizeHint(sovi, index);
|
||||
if (itemSizeHint.width() > width)
|
||||
width = itemSizeHint.width();
|
||||
|
||||
// height
|
||||
const int nextHeight = height + itemSizeHint.height();
|
||||
if (nextHeight + vOffset < this->maximumHeight())
|
||||
height = nextHeight;
|
||||
else {
|
||||
// early termination
|
||||
vScrollOn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QSize sizeHint(width + hOffset, 0);
|
||||
sizeHint.setHeight(height + vOffset);
|
||||
if (vScrollOn) {
|
||||
int scrollWidth = this->verticalScrollBar()->sizeHint().width();
|
||||
sizeHint.setWidth(sizeHint.width() + scrollWidth);
|
||||
}
|
||||
return sizeHint;
|
||||
}
|
||||
|
||||
void PopupListWidget::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Tab ||
|
||||
e->key() == Qt::Key_Return)
|
||||
Q_EMIT itemActivated(currentItem());
|
||||
else
|
||||
QListWidget::keyPressEvent(e);
|
||||
}
|
||||
|
||||
PopupCompleter::PopupCompleter(const QStringList& sl, QWidget *parent)
|
||||
: QDialog(parent, Qt::Popup)
|
||||
{
|
||||
setModal(true);
|
||||
|
||||
listWidget_ = new PopupListWidget();
|
||||
listWidget_->setMaximumHeight(200);
|
||||
qDebug() << "sizeHint(): " << listWidget_->sizeHint();
|
||||
Q_FOREACH(QString str, sl) {
|
||||
QListWidgetItem *item = new QListWidgetItem;
|
||||
item->setText(str);
|
||||
listWidget_->addItem(item);
|
||||
}
|
||||
qDebug() << "sizeHint(): " << listWidget_->sizeHint();
|
||||
listWidget_->setFixedSize(listWidget_->sizeHint());
|
||||
|
||||
|
||||
QLayout *layout = new QVBoxLayout();
|
||||
layout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(listWidget_);
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
// connect signal
|
||||
connect(listWidget_, SIGNAL(itemActivated(QListWidgetItem *)),
|
||||
SLOT(onItemActivated(QListWidgetItem*)));
|
||||
}
|
||||
|
||||
PopupCompleter::~PopupCompleter()
|
||||
{
|
||||
}
|
||||
|
||||
void PopupCompleter::showEvent(QShowEvent *event)
|
||||
{
|
||||
listWidget_->setFocus();
|
||||
}
|
||||
|
||||
void PopupCompleter::onItemActivated(QListWidgetItem *event)
|
||||
{
|
||||
selected_ = event->text();
|
||||
done(QDialog::Accepted);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief execute PopupCompleter at appropriate position.
|
||||
*
|
||||
* @param parent Parent of this popup completer. usually QConsole.
|
||||
* @return see QDialog::exec
|
||||
* @see QDialog::exec
|
||||
*/
|
||||
int PopupCompleter::exec(QTextEdit *parent)
|
||||
{
|
||||
QSize popupSizeHint = this->sizeHint();
|
||||
QRect cursorRect = parent->cursorRect();
|
||||
QPoint globalPt = parent->mapToGlobal(cursorRect.bottomRight());
|
||||
QDesktopWidget *dsk = QApplication::desktop();
|
||||
QRect screenGeom = dsk->screenGeometry(dsk->screenNumber(this));
|
||||
if (globalPt.y() + popupSizeHint.height() > screenGeom.height()) {
|
||||
globalPt = parent->mapToGlobal(cursorRect.topRight());
|
||||
globalPt.setY(globalPt.y() - popupSizeHint.height());
|
||||
}
|
||||
this->move(globalPt);
|
||||
this->setFocus();
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a common word of the given list
|
||||
*
|
||||
* @param list String list
|
||||
*
|
||||
* @return common word in the given string.
|
||||
*/
|
||||
static
|
||||
QString getCommonWord(QStringList& list)
|
||||
{
|
||||
QChar ch;
|
||||
QVector<QString> strarray = list.toVector();
|
||||
QString common;
|
||||
int col = 0, min_len;
|
||||
bool cont = true;
|
||||
|
||||
// get minimum length
|
||||
min_len = strarray.at(0).size();
|
||||
for (int i=1; i<strarray.size(); ++i) {
|
||||
const int len = strarray.at(i).size();
|
||||
if (len < min_len)
|
||||
min_len = len;
|
||||
}
|
||||
|
||||
while(col < min_len) {
|
||||
ch = strarray.at(0)[col];
|
||||
for (int i=1; i<strarray.size(); ++i) {
|
||||
const QString& current_string = strarray.at(i);
|
||||
if (ch != current_string[col])
|
||||
{
|
||||
cont = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cont)
|
||||
break;
|
||||
|
||||
common.push_back(ch);
|
||||
++col;
|
||||
}
|
||||
return common;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Clear the console
|
||||
void QConsole::clear()
|
||||
{
|
||||
QTextEdit::clear();
|
||||
}
|
||||
|
||||
//Reset the console
|
||||
void QConsole::reset(const QString &welcomeText)
|
||||
{
|
||||
clear();
|
||||
|
||||
append(welcomeText);
|
||||
append("");
|
||||
|
||||
//init attributes
|
||||
historyIndex = 0;
|
||||
history.clear();
|
||||
recordedScript.clear();
|
||||
}
|
||||
|
||||
//QConsole constructor (init the QTextEdit & the attributes)
|
||||
QConsole::QConsole(QWidget *parent, const QString &welcomeText)
|
||||
: QTextEdit(parent), errColor_(Qt::red),
|
||||
outColor_(Qt::white), completionColor(Qt::darkGreen),
|
||||
promptLength(0), promptParagraph(0), isLocked(false)
|
||||
{
|
||||
// Disable accepting rich text from user
|
||||
setAcceptRichText(false);
|
||||
|
||||
//Disable undo/redo
|
||||
setUndoRedoEnabled(false);
|
||||
|
||||
|
||||
//Disable context menu
|
||||
//This menu is useful for undo/redo, cut/copy/paste, del, select all,
|
||||
// see function QConsole::contextMenuEvent(...)
|
||||
//setContextMenuPolicy(Qt::NoContextMenu);
|
||||
|
||||
|
||||
//resets the console
|
||||
reset(welcomeText);
|
||||
const int tabwidth = QFontMetrics(currentFont()).width('a') * 4;
|
||||
setTabStopWidth(tabwidth);
|
||||
}
|
||||
|
||||
//Sets the prompt and cache the prompt length to optimize the processing speed
|
||||
void QConsole::setPrompt(const QString &newPrompt, bool display)
|
||||
{
|
||||
prompt = newPrompt;
|
||||
promptLength = prompt.length();
|
||||
//display the new prompt
|
||||
if (display)
|
||||
displayPrompt();
|
||||
}
|
||||
|
||||
|
||||
//Displays the prompt and move the cursor to the end of the line.
|
||||
void QConsole::displayPrompt()
|
||||
{
|
||||
//Prevent previous text displayed to be undone
|
||||
setUndoRedoEnabled(false);
|
||||
//displays the prompt
|
||||
setTextColor(cmdColor_);
|
||||
QTextCursor cur = textCursor();
|
||||
cur.insertText(prompt);
|
||||
cur.movePosition(QTextCursor::EndOfLine);
|
||||
setTextCursor(cur);
|
||||
//Saves the paragraph number of the prompt
|
||||
promptParagraph = cur.blockNumber();
|
||||
|
||||
//Enable undo/redo for the actual command
|
||||
setUndoRedoEnabled(true);
|
||||
}
|
||||
|
||||
void QConsole::setFont(const QFont& f) {
|
||||
QTextCharFormat format;
|
||||
QTextCursor oldCursor = textCursor();
|
||||
format.setFont(f);
|
||||
selectAll();
|
||||
textCursor().setBlockCharFormat(format);
|
||||
setCurrentFont(f);
|
||||
setTextCursor(oldCursor);
|
||||
}
|
||||
|
||||
//Give suggestions to autocomplete a command (should be reimplemented)
|
||||
//the return value of the function is the string list of all suggestions
|
||||
QStringList QConsole::suggestCommand(const QString&, QString& prefix)
|
||||
{
|
||||
prefix = "";
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
//Treat the tab key & autocomplete the current command
|
||||
void QConsole::handleTabKeyPress()
|
||||
{
|
||||
QString command = getCurrentCommand();
|
||||
QString commandPrefix;
|
||||
QStringList sl = suggestCommand(command, commandPrefix);
|
||||
if (sl.count() == 0)
|
||||
textCursor().insertText("\t");
|
||||
else {
|
||||
if (sl.count() == 1)
|
||||
replaceCurrentCommand(commandPrefix + sl[0]);
|
||||
else
|
||||
{
|
||||
// common word completion
|
||||
QString commonWord = getCommonWord(sl);
|
||||
command = commonWord;
|
||||
|
||||
PopupCompleter *popup = new PopupCompleter(sl);
|
||||
if (popup->exec(this) == QDialog::Accepted)
|
||||
replaceCurrentCommand(commandPrefix + popup->selected());
|
||||
delete popup;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If return pressed, do the evaluation and append the result
|
||||
void QConsole::handleReturnKeyPress()
|
||||
{
|
||||
//Get the command to validate
|
||||
QString command = getCurrentCommand();
|
||||
//execute the command and get back its text result and its return value
|
||||
if (isCommandComplete(command))
|
||||
pExecCommand(command);
|
||||
else
|
||||
{
|
||||
append("");
|
||||
moveCursor(QTextCursor::EndOfLine);
|
||||
}
|
||||
}
|
||||
|
||||
bool QConsole::handleBackspaceKeyPress()
|
||||
{
|
||||
QTextCursor cur = textCursor();
|
||||
const int col = cur.columnNumber();
|
||||
const int blk = cur.blockNumber();
|
||||
if (blk == promptParagraph && col == promptLength)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void QConsole::handleUpKeyPress()
|
||||
{
|
||||
if (history.count())
|
||||
{
|
||||
QString command = getCurrentCommand();
|
||||
do
|
||||
{
|
||||
if (historyIndex)
|
||||
historyIndex--;
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while(history[historyIndex] == command);
|
||||
replaceCurrentCommand(history[historyIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
void QConsole::handleDownKeyPress()
|
||||
{
|
||||
if (history.count())
|
||||
{
|
||||
QString command = getCurrentCommand();
|
||||
do
|
||||
{
|
||||
if (++historyIndex >= history.size())
|
||||
{
|
||||
historyIndex = history.size() - 1;
|
||||
break;
|
||||
}
|
||||
} while(history[historyIndex] == command);
|
||||
replaceCurrentCommand(history[historyIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QConsole::setHome(bool select)
|
||||
{
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.movePosition(QTextCursor::StartOfBlock, select ? QTextCursor::KeepAnchor :
|
||||
QTextCursor::MoveAnchor);
|
||||
if(textCursor().blockNumber() == promptParagraph)
|
||||
{
|
||||
cursor.movePosition(QTextCursor::Right, select ? QTextCursor::KeepAnchor :
|
||||
QTextCursor::MoveAnchor,
|
||||
promptLength);
|
||||
}
|
||||
setTextCursor(cursor);
|
||||
}
|
||||
|
||||
//Reimplemented key press event
|
||||
void QConsole::keyPressEvent( QKeyEvent *e )
|
||||
{
|
||||
if (isLocked)
|
||||
return;
|
||||
|
||||
//If the user wants to copy or cut outside
|
||||
//the editing area we perform a copy
|
||||
if(textCursor().hasSelection())
|
||||
{
|
||||
if(e->modifiers() == Qt::CTRL)
|
||||
{
|
||||
if( e->matches(QKeySequence::Cut) )
|
||||
{
|
||||
e->accept();
|
||||
if(!isInEditionZone())
|
||||
{
|
||||
copy();
|
||||
}
|
||||
else
|
||||
{
|
||||
cut();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(e->matches(QKeySequence::Copy) )
|
||||
{
|
||||
e->accept();
|
||||
copy();
|
||||
}
|
||||
else
|
||||
{
|
||||
QTextEdit::keyPressEvent( e );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
// if the cursor out of editing zone put it back first
|
||||
if(!isInEditionZone())
|
||||
{
|
||||
QTextCursor editCursor = textCursor();
|
||||
editCursor.setPosition(oldEditPosition);
|
||||
setTextCursor(editCursor);
|
||||
}
|
||||
*/
|
||||
// control is pressed
|
||||
if ( (e->modifiers() & Qt::ControlModifier) && (e->key() == Qt::Key_C) )
|
||||
{
|
||||
if ( isSelectionInEditionZone())
|
||||
{
|
||||
//If Ctrl + C pressed, then undo the current commant
|
||||
//append("");
|
||||
//displayPrompt();
|
||||
|
||||
//(Thierry Belair:)I humbly suggest that ctrl+C copies the text, as is expected,
|
||||
//and indicated in the contextual menu
|
||||
copy();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
switch (e->key()) {
|
||||
case Qt::Key_Tab:
|
||||
if(isSelectionInEditionZone())
|
||||
{
|
||||
handleTabKeyPress();
|
||||
}
|
||||
return;
|
||||
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
if (isSelectionInEditionZone())
|
||||
{
|
||||
handleReturnKeyPress();
|
||||
}
|
||||
// ignore return key
|
||||
return;
|
||||
|
||||
case Qt::Key_Backspace:
|
||||
if (handleBackspaceKeyPress() || !isSelectionInEditionZone())
|
||||
return;
|
||||
break;
|
||||
|
||||
case Qt::Key_Home:
|
||||
setHome(e->modifiers() & Qt::ShiftModifier);
|
||||
case Qt::Key_Down:
|
||||
if (isInEditionZone())
|
||||
{
|
||||
handleDownKeyPress();
|
||||
}
|
||||
return;
|
||||
case Qt::Key_Up:
|
||||
if (isInEditionZone())
|
||||
{
|
||||
handleUpKeyPress();
|
||||
}
|
||||
return;
|
||||
|
||||
//Default behaviour
|
||||
case Qt::Key_End:
|
||||
case Qt::Key_Left:
|
||||
case Qt::Key_Right:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (textCursor().hasSelection() ) {
|
||||
if (!isSelectionInEditionZone())
|
||||
{
|
||||
moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{ //no selection
|
||||
//when typing normal characters,
|
||||
//make sure the cursor is positionned in the
|
||||
//edition zone
|
||||
if ( !isInEditionZone() )
|
||||
{
|
||||
moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
|
||||
}
|
||||
}
|
||||
} //end of switch
|
||||
} //end of else : no control pressed
|
||||
|
||||
QTextEdit::keyPressEvent( e );
|
||||
}
|
||||
|
||||
//Get the current command
|
||||
QString QConsole::getCurrentCommand()
|
||||
{
|
||||
QTextCursor cursor = textCursor(); //Get the current command: we just remove the prompt
|
||||
cursor.movePosition(QTextCursor::StartOfBlock);
|
||||
cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, promptLength);
|
||||
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
QString command = cursor.selectedText();
|
||||
cursor.clearSelection();
|
||||
return command;
|
||||
}
|
||||
|
||||
//Replace current command with a new one
|
||||
void QConsole::replaceCurrentCommand(const QString &newCommand)
|
||||
{
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.movePosition(QTextCursor::StartOfLine);
|
||||
cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, promptLength);
|
||||
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
|
||||
cursor.insertText(newCommand);
|
||||
}
|
||||
|
||||
//default implementation: command always complete
|
||||
bool QConsole::isCommandComplete(const QString &)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//Tests whether the cursor is in th edition zone or not (after the prompt
|
||||
//or in the next lines (in case of multi-line mode)
|
||||
bool QConsole::isInEditionZone()
|
||||
{
|
||||
const int para = textCursor().blockNumber();
|
||||
const int index = textCursor().columnNumber();
|
||||
return (para > promptParagraph) || ( (para == promptParagraph) && (index >= promptLength) );
|
||||
}
|
||||
|
||||
|
||||
//Tests whether position (in parameter) is in the edition zone or not (after the prompt
|
||||
//or in the next lines (in case of multi-line mode)
|
||||
bool QConsole::isInEditionZone(const int& pos)
|
||||
{
|
||||
QTextCursor cur = textCursor();
|
||||
cur.setPosition(pos);
|
||||
const int para = cur.blockNumber();
|
||||
const int index = cur.columnNumber();
|
||||
return (para > promptParagraph) || ( (para == promptParagraph) && (index >= promptLength) );
|
||||
}
|
||||
|
||||
|
||||
//Tests whether the current selection is in th edition zone or not
|
||||
bool QConsole::isSelectionInEditionZone()
|
||||
{
|
||||
QTextCursor cursor(document());
|
||||
int range[2];
|
||||
|
||||
range[0] = textCursor().selectionStart();
|
||||
range[1] = textCursor().selectionEnd();
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
cursor.setPosition(range[i]);
|
||||
int para = cursor.blockNumber();
|
||||
int index = cursor.columnNumber();
|
||||
if ((para <= promptParagraph) && ( (para != promptParagraph) || (index < promptLength) ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//Basically, puts the command into the history list
|
||||
//And emits a signal (should be called by reimplementations)
|
||||
QString QConsole::addCommandToHistory(const QString &command)
|
||||
{
|
||||
//Add the command to the recordedScript list
|
||||
recordedScript.append(command);
|
||||
//update the history and its index
|
||||
QString modifiedCommand = command;
|
||||
modifiedCommand.replace("\n", "\\n");
|
||||
history.append(modifiedCommand);
|
||||
historyIndex = history.size();
|
||||
//emit the commandExecuted signal
|
||||
Q_EMIT commandAddedToHistory(modifiedCommand);
|
||||
return "";
|
||||
}
|
||||
|
||||
//pExecCommand(QString) executes the command and displays back its result
|
||||
void QConsole::pExecCommand(const QString &command)
|
||||
{
|
||||
isLocked = true;
|
||||
|
||||
addCommandToHistory(command);
|
||||
|
||||
emit execCommand(command);
|
||||
}
|
||||
|
||||
void QConsole::printCommandExecutionResults(const QString &result, ResultType type)
|
||||
{
|
||||
//According to the return value, display the result either in red or in blue
|
||||
if (type == ResultType::Error)
|
||||
setTextColor(errColor_);
|
||||
else
|
||||
setTextColor(outColor_);
|
||||
|
||||
append(result);
|
||||
|
||||
//Display the prompt again
|
||||
if (type == ResultType::Complete || type == ResultType::Error) {
|
||||
if (!result.endsWith("\n"))
|
||||
append("\n");
|
||||
|
||||
isLocked = false;
|
||||
displayPrompt();
|
||||
}
|
||||
|
||||
moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Change paste behaviour
|
||||
void QConsole::insertFromMimeData(const QMimeData *source)
|
||||
{
|
||||
if (isSelectionInEditionZone())
|
||||
{
|
||||
QTextEdit::insertFromMimeData(source);
|
||||
}
|
||||
}
|
||||
|
||||
//Implement paste with middle mouse button
|
||||
void QConsole::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
oldPosition = textCursor().position();
|
||||
if (event->button() == Qt::MidButton)
|
||||
{
|
||||
copy();
|
||||
QTextCursor cursor = cursorForPosition(event->pos());
|
||||
setTextCursor(cursor);
|
||||
paste();
|
||||
return;
|
||||
}
|
||||
|
||||
QTextEdit::mousePressEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//Redefinition of the dropEvent to have a copy paste
|
||||
//instead of a cut paste when copying out of the
|
||||
//editable zone
|
||||
void QConsole::dropEvent ( QDropEvent * event)
|
||||
{
|
||||
if(!isInEditionZone())
|
||||
{
|
||||
//Execute un drop a drop at the old position
|
||||
//if the drag started out of the editable zone
|
||||
QTextCursor cur = textCursor();
|
||||
cur.setPosition(oldPosition);
|
||||
setTextCursor(cur);
|
||||
}
|
||||
//Execute a normal drop
|
||||
QTextEdit::dropEvent(event);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void QConsole::dragMoveEvent( QDragMoveEvent * event)
|
||||
{
|
||||
//Get a cursor for the actual mouse position
|
||||
QTextCursor cur = textCursor();
|
||||
cur.setPosition(cursorForPosition(event->pos()).position());
|
||||
|
||||
if(!isInEditionZone(cursorForPosition(event->pos()).position()))
|
||||
{
|
||||
//Ignore the event if out of the editable zone
|
||||
event->ignore(cursorRect(cur));
|
||||
}
|
||||
else
|
||||
{
|
||||
//Accept the event if out of the editable zone
|
||||
event->accept(cursorRect(cur));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QConsole::contextMenuEvent ( QContextMenuEvent * event)
|
||||
{
|
||||
if (isLocked)
|
||||
return;
|
||||
|
||||
QMenu *menu = new QMenu(this);
|
||||
|
||||
QAction *undo = new QAction(tr("Undo"), this);
|
||||
undo->setShortcut(tr("Ctrl+Z"));
|
||||
QAction *redo = new QAction(tr("Redo"), this);
|
||||
redo->setShortcut(tr("Ctrl+Y"));
|
||||
QAction *cut = new QAction(tr("Cut"), this);
|
||||
cut->setShortcut(tr("Ctrl+X"));
|
||||
QAction *copy = new QAction(tr("Copy"), this);
|
||||
copy->setShortcut(tr("Ctrl+Ins"));
|
||||
QAction *paste = new QAction(tr("Paste"), this);
|
||||
paste->setShortcut(tr("Ctrl+V"));
|
||||
QAction *del = new QAction(tr("Delete"), this);
|
||||
del->setShortcut(tr("Del"));
|
||||
QAction *selectAll = new QAction(tr("Select All"), this);
|
||||
selectAll->setShortcut(tr("Ctrl+A"));
|
||||
|
||||
menu->addAction(undo);
|
||||
menu->addAction(redo);
|
||||
menu->addSeparator();
|
||||
menu->addAction(cut);
|
||||
menu->addAction(copy);
|
||||
menu->addAction(paste);
|
||||
menu->addAction(del);
|
||||
menu->addSeparator();
|
||||
menu->addAction(selectAll);
|
||||
|
||||
connect(undo, SIGNAL(triggered()), this, SLOT(undo()));
|
||||
connect(redo, SIGNAL(triggered()), this, SLOT(redo()));
|
||||
connect(cut, SIGNAL(triggered()), this, SLOT(cut()));
|
||||
connect(copy, SIGNAL(triggered()), this, SLOT(copy()));
|
||||
connect(paste, SIGNAL(triggered()), this, SLOT(paste()));
|
||||
connect(del, SIGNAL(triggered()), this, SLOT(del()));
|
||||
connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAll()));
|
||||
|
||||
|
||||
menu->exec(event->globalPos());
|
||||
|
||||
delete menu;
|
||||
}
|
||||
|
||||
void QConsole::cut()
|
||||
{
|
||||
//Cut only in the editing zone,
|
||||
//perfom a copy otherwise
|
||||
if(isSelectionInEditionZone())
|
||||
{
|
||||
QTextEdit::cut();
|
||||
return;
|
||||
}
|
||||
|
||||
QTextEdit::copy();
|
||||
}
|
||||
|
||||
/*
|
||||
//Allows pasting with middle mouse button (x window)
|
||||
//when clicking outside of the edition zone
|
||||
void QConsole::paste()
|
||||
{
|
||||
restoreOldPosition();
|
||||
QTextEdit::paste();
|
||||
}
|
||||
*/
|
||||
|
||||
void QConsole::del()
|
||||
{
|
||||
//Delete only in the editing zone
|
||||
if(isInEditionZone())
|
||||
{
|
||||
textCursor().movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
|
||||
textCursor().deleteChar();
|
||||
}
|
||||
}
|
||||
|
||||
void QConsole::correctPathName(QString& pathName)
|
||||
{
|
||||
if(pathName.contains(tr(":\\")))
|
||||
{
|
||||
pathName.replace('\\', tr("/"));
|
||||
}
|
||||
}
|
||||
211
system/clearpilot/tools_wip_4_28/QConsole.h
Normal file
211
system/clearpilot/tools_wip_4_28/QConsole.h
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
Change log:
|
||||
(C) 2005 by Houssem BDIOUI <houssem.bdioui@gmail.com>
|
||||
(C) 2010 by YoungTaek Oh. (migrated to Qt4)
|
||||
(C) 2014-2015 Igor Malinovskiy
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QStringList>
|
||||
#include <QTextEdit>
|
||||
#include <QMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QMenu>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QListWidget>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
/**
|
||||
* Subclasssing QListWidget
|
||||
*
|
||||
* @author YoungTaek Oh
|
||||
*/
|
||||
class PopupListWidget : public QListWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PopupListWidget(QWidget *parent = 0): QListWidget(parent) {
|
||||
setUniformItemSizes(true);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
virtual ~PopupListWidget() { }
|
||||
|
||||
protected:
|
||||
virtual QSize sizeHint() const;
|
||||
virtual void keyPressEvent(QKeyEvent *e);
|
||||
};
|
||||
|
||||
/**
|
||||
* Popup Completer class
|
||||
*
|
||||
* @author YoungTaek Oh
|
||||
* @todo 1. beautifying
|
||||
* 2. icons for classifying words (eg. functions, properties...)
|
||||
* 3. bugs?
|
||||
* @note still experimental
|
||||
*/
|
||||
class PopupCompleter : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PopupCompleter(const QStringList&, QWidget *parent = 0);
|
||||
virtual ~PopupCompleter();
|
||||
|
||||
public:
|
||||
QString selected(void) { return selected_; }
|
||||
int exec(QTextEdit*);
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent*);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onItemActivated(QListWidgetItem*);
|
||||
|
||||
public:
|
||||
QListWidget *listWidget_;
|
||||
QString selected_;
|
||||
};
|
||||
|
||||
/**
|
||||
* An abstract Qt console
|
||||
* @author Houssem BDIOUI
|
||||
*/
|
||||
class QConsole : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
//constructor
|
||||
QConsole(QWidget *parent = NULL, const QString &welcomeText = "");
|
||||
//set the prompt of the console
|
||||
void setPrompt(const QString &prompt, bool display = true);
|
||||
|
||||
//clear & reset the console (useful sometimes)
|
||||
void clear();
|
||||
void reset(const QString &welcomeText = "");
|
||||
|
||||
//cosmetic methods !
|
||||
|
||||
// @{
|
||||
/// get/set command color
|
||||
QColor cmdColor() const { return cmdColor_; }
|
||||
void setCmdColor(QColor c) {cmdColor_ = c;}
|
||||
// @}
|
||||
|
||||
// @{
|
||||
/// get/set error color
|
||||
QColor errColor() const { return errColor_; }
|
||||
void setErrColor(QColor c) {errColor_ = c;}
|
||||
// @}
|
||||
|
||||
// @{
|
||||
/// get/set output color
|
||||
QColor outColor() const { return outColor_; }
|
||||
void setOutColor(QColor c) {outColor_ = c;}
|
||||
// @}
|
||||
void setCompletionColor(QColor c) {completionColor = c;}
|
||||
|
||||
// @{
|
||||
/// get set font
|
||||
void setFont(const QFont& f);
|
||||
QFont font() const { return currentFont(); }
|
||||
// @}
|
||||
|
||||
void correctPathName(QString& pathName);
|
||||
|
||||
enum ResultType {Error, Partial, Complete};
|
||||
|
||||
private:
|
||||
void dropEvent( QDropEvent * event);
|
||||
void dragMoveEvent( QDragMoveEvent * event);
|
||||
|
||||
void keyPressEvent(QKeyEvent * e);
|
||||
void contextMenuEvent( QContextMenuEvent * event);
|
||||
|
||||
//Return false if the command is incomplete (e.g. unmatched braces)
|
||||
virtual bool isCommandComplete(const QString &command);
|
||||
//Get the command to validate
|
||||
QString getCurrentCommand();
|
||||
|
||||
//Replace current command with a new one
|
||||
void replaceCurrentCommand(const QString &newCommand);
|
||||
|
||||
//Test whether the cursor is in the edition zone
|
||||
bool isInEditionZone();
|
||||
bool isInEditionZone(const int& pos);
|
||||
|
||||
//Test whether the selection is in the edition zone
|
||||
bool isSelectionInEditionZone();
|
||||
//Change paste behaviour
|
||||
void insertFromMimeData(const QMimeData *);
|
||||
|
||||
protected:
|
||||
//colors
|
||||
QColor cmdColor_, errColor_, outColor_, completionColor;
|
||||
|
||||
int oldPosition;
|
||||
// cached prompt length
|
||||
int promptLength;
|
||||
// The prompt string
|
||||
QString prompt;
|
||||
// The commands history
|
||||
QStringList history;
|
||||
//Contains the commands that has succeeded
|
||||
QStringList recordedScript;
|
||||
// Current history index (needed because afaik QStringList does not have such an index)
|
||||
int historyIndex;
|
||||
//Holds the paragraph number of the prompt (useful for multi-line command handling)
|
||||
int promptParagraph;
|
||||
|
||||
protected:
|
||||
//Implement paste with middle mouse button
|
||||
void mousePressEvent(QMouseEvent*);
|
||||
|
||||
//execute a validated command (should be reimplemented and called at the end)
|
||||
//the return value of the function is the string result
|
||||
//res must hold back the return value of the command (0: passed; else: error)
|
||||
virtual QString addCommandToHistory(const QString &command);
|
||||
|
||||
//give suggestions to autocomplete a command (should be reimplemented)
|
||||
//the return value of the function is the string list of all suggestions
|
||||
//the returned prefix is useful to complete "sub-commands"
|
||||
virtual QStringList suggestCommand(const QString &cmd, QString &prefix);
|
||||
|
||||
|
||||
public slots:
|
||||
//Contextual menu slots
|
||||
void cut();
|
||||
//void paste();
|
||||
void del();
|
||||
//displays the prompt
|
||||
void displayPrompt();
|
||||
|
||||
void printCommandExecutionResults(const QString &, ResultType t = ResultType::Complete);
|
||||
|
||||
signals:
|
||||
//Signal emitted after that a command is executed
|
||||
void commandAddedToHistory(const QString &command);
|
||||
void execCommand(const QString &command);
|
||||
|
||||
private:
|
||||
bool isLocked;
|
||||
|
||||
void handleTabKeyPress();
|
||||
void handleReturnKeyPress();
|
||||
bool handleBackspaceKeyPress();
|
||||
void handleUpKeyPress();
|
||||
void handleDownKeyPress();
|
||||
void setHome(bool);
|
||||
void pExecCommand(const QString &command);
|
||||
};
|
||||
|
||||
#include "QConsole.cc"
|
||||
@@ -0,0 +1,10 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: RotationModule
|
||||
Version: 1.0
|
||||
Summary: Module for rotating display via native interface
|
||||
Home-page: UNKNOWN
|
||||
Author: UNKNOWN
|
||||
Author-email: UNKNOWN
|
||||
License: UNKNOWN
|
||||
Description: UNKNOWN
|
||||
Platform: UNKNOWN
|
||||
@@ -0,0 +1,6 @@
|
||||
rotation_module.cc
|
||||
rotation_module_build.py
|
||||
RotationModule.egg-info/PKG-INFO
|
||||
RotationModule.egg-info/SOURCES.txt
|
||||
RotationModule.egg-info/dependency_links.txt
|
||||
RotationModule.egg-info/top_level.txt
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
rotation
|
||||
17
system/clearpilot/tools_wip_4_28/decrypt
Normal file
17
system/clearpilot/tools_wip_4_28/decrypt
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check for the correct number of arguments
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "Usage: $0 source destination"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set variables for source and destination
|
||||
src="$1"
|
||||
dest="$2"
|
||||
|
||||
# Read DongleId for decryption key
|
||||
dongle_id=/data/params/d/DongleId
|
||||
|
||||
# Decrypt the file
|
||||
cat "$src" | ccrypt -d -k "$dongle_id" > "$dest"
|
||||
17
system/clearpilot/tools_wip_4_28/encrypt
Normal file
17
system/clearpilot/tools_wip_4_28/encrypt
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check for the correct number of arguments
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "Usage: $0 source destination"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set variables for source and destination
|
||||
src="$1"
|
||||
dest="$2"
|
||||
|
||||
# Read DongleId for encryption key
|
||||
dongle_id=/data/params/d/DongleId
|
||||
|
||||
# Encrypt the file
|
||||
cat "$src" | ccrypt -e -k "$dongle_id" > "$dest"
|
||||
81
system/clearpilot/tools_wip_4_28/faketty.py
Normal file
81
system/clearpilot/tools_wip_4_28/faketty.py
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from sys import argv
|
||||
import os
|
||||
import signal
|
||||
|
||||
# I've had problems with python's File objects at this low a level, so
|
||||
# we're going to use integers to specify all files in this script.
|
||||
stdin = 0
|
||||
stdout = 1
|
||||
stderr = 2
|
||||
# Include this if passing the command and arguments to fish to
|
||||
# prevent fish from applying any expansions.
|
||||
#import re
|
||||
#def fish_escape(args):
|
||||
# def escape_one(arg):
|
||||
# return "'" + re.sub(r"('|\\)", r'\\\1', arg) + "'"
|
||||
# escaped_args = map(escape_one, args)
|
||||
# return ' '.join(escaped_args)
|
||||
|
||||
if len(argv) < 2:
|
||||
os.write(stderr,
|
||||
b"""A tragically beautiful piece of hackery, made to fool programs like ls,
|
||||
grep, rg, and fd into thinking they're actually connected to a terminal.
|
||||
Its usage:
|
||||
|
||||
pty command [arg1 arg2 ...]
|
||||
|
||||
Examples:
|
||||
pty ls --color -R | less -r
|
||||
git log -p | pty rg <search terms> | less -r
|
||||
""")
|
||||
exit(255)
|
||||
|
||||
# We do not use forkpty here because it would block ^Cs from reaching the
|
||||
# child process. And we don't need that.
|
||||
ptm, pts = os.openpty()
|
||||
pid = os.fork()
|
||||
if pid == 0:
|
||||
# The child runs this.
|
||||
# To get the behaviour we want, we only need to replace the process's
|
||||
# stdout with pts. Everything else should remain in place, so that things
|
||||
# like `ps -eF | pty rg python | less -r` will still work as intended.
|
||||
os.dup2(pts, stdout)
|
||||
# This is not like a subprocess.call(). It replaces the entire child
|
||||
# process with argv[1:], meaning execvp will not return! Web search
|
||||
# "fork exec" for more.
|
||||
os.execvp(argv[1], argv[1:])
|
||||
# Use this if calling fish.
|
||||
#os.execvp('fish', ['fish', '-c', fish_escape(argv[1:])])
|
||||
|
||||
|
||||
# The parent runs this.
|
||||
|
||||
# If the parent doesn't close the slave end, the script won't be able to
|
||||
# exit. The next read on ptm after the child process terminates would hang
|
||||
# forever because pts would technically still be open.
|
||||
os.close(pts)
|
||||
|
||||
# The whole process group gets SIGINT, including the child, so we don't need
|
||||
# to react to it. We'll know when to leave, judging by what the child does.
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
|
||||
while True:
|
||||
try:
|
||||
chunk = os.read(ptm, 4096)
|
||||
except OSError:
|
||||
break
|
||||
try:
|
||||
os.write(stdout, chunk)
|
||||
except BrokenPipeError:
|
||||
# This happens when the parent is piping output to another process in a
|
||||
# pipeline, like in `pty ls --color -R | less -r`, and the receiving
|
||||
# process is terminated before the child has exited. If the receiving
|
||||
# process is less, this can happen very easily. It happens every time
|
||||
# the user decides to quit less before it has displayed all output. So,
|
||||
# we need to stop the child process now.
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
break
|
||||
wait_pid, status = os.waitpid(pid, 0)
|
||||
exit(status >> 8)
|
||||
188
system/clearpilot/tools_wip_4_28/moc_test2.cc
Normal file
188
system/clearpilot/tools_wip_4_28/moc_test2.cc
Normal file
@@ -0,0 +1,188 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'test2.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "test2.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'test2.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_TrackWidget_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata0[12];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_TrackWidget_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_TrackWidget_t qt_meta_stringdata_TrackWidget = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 11) // "TrackWidget"
|
||||
|
||||
},
|
||||
"TrackWidget"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_TrackWidget[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void TrackWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject TrackWidget::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_TrackWidget.data,
|
||||
qt_meta_data_TrackWidget,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *TrackWidget::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *TrackWidget::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_TrackWidget.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int TrackWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
return _id;
|
||||
}
|
||||
struct qt_meta_stringdata_Spinner_t {
|
||||
QByteArrayData data[4];
|
||||
char stringdata0[18];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_Spinner_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_Spinner_t qt_meta_stringdata_Spinner = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 7), // "Spinner"
|
||||
QT_MOC_LITERAL(1, 8, 6), // "update"
|
||||
QT_MOC_LITERAL(2, 15, 0), // ""
|
||||
QT_MOC_LITERAL(3, 16, 1) // "n"
|
||||
|
||||
},
|
||||
"Spinner\0update\0\0n"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_Spinner[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
1, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
1, 1, 19, 2, 0x0a /* Public */,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, QMetaType::Int, 3,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void Spinner::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<Spinner *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->update((*reinterpret_cast< int(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject Spinner::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_Spinner.data,
|
||||
qt_meta_data_Spinner,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *Spinner::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *Spinner::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_Spinner.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int Spinner::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 1)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 1;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 1)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 1;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
41
system/clearpilot/tools_wip_4_28/provision.sh
Normal file
41
system/clearpilot/tools_wip_4_28/provision.sh
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Provision script for BrianBot
|
||||
# These actions only occur on BrianBot's comma device.
|
||||
|
||||
# 1. Check the string in /data/params/d/DongleId
|
||||
dongle_id=$(cat /data/params/d/DongleId)
|
||||
if [[ ! $dongle_id == 90bb71a* ]]; then
|
||||
echo "Invalid dongle ID."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "BrianBot dongle ID detected."
|
||||
|
||||
# 2. Check if ccrypt is installed, install if not
|
||||
if ! command -v ccrypt >/dev/null 2>&1; then
|
||||
echo "Installing ccrypt..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ccrypt
|
||||
fi
|
||||
|
||||
# 3. Decrypt SSH keys if they have not been decrypted yet
|
||||
if [ ! -f /data/openpilot/system/clearpilot/dev/id_rsa.pub ]; then
|
||||
echo "Decrypting SSH keys..."
|
||||
ccrypt -d -k "$dongle_id" /data/openpilot/system/clearpilot/dev/id_rsa.pub.ccrypt
|
||||
ccrypt -d -k "$dongle_id" /data/openpilot/system/clearpilot/dev/id_rsa.ccrypt
|
||||
ccrypt -d -k "$dongle_id" /data/openpilot/system/clearpilot/dev/reverse_ssh.ccrypt
|
||||
fi
|
||||
|
||||
# 4. Ensure .ssh directory and keys exist
|
||||
ssh_dir="/home/comma/.ssh"
|
||||
if [[ ! -f "$ssh_dir/id_rsa" || ! -f "$ssh_dir/id_rsa.pub" ]]; then
|
||||
echo "Setting up SSH directory and keys..."
|
||||
mkdir -p "$ssh_dir"
|
||||
cp /data/openpilot/system/clearpilot/dev/id_rsa /data/openpilot/system/clearpilot/dev/id_rsa.pub "$ssh_dir"
|
||||
chmod 700 "$ssh_dir"
|
||||
chmod 600 "$ssh_dir/id_rsa" "$ssh_dir/id_rsa.pub"
|
||||
fi
|
||||
|
||||
echo "Script execution complete."
|
||||
exit 0
|
||||
1
system/clearpilot/tools_wip_4_28/remount_ro.sh
Normal file
1
system/clearpilot/tools_wip_4_28/remount_ro.sh
Normal file
@@ -0,0 +1 @@
|
||||
sudo mount -o remount,ro /
|
||||
1
system/clearpilot/tools_wip_4_28/remount_rw.sh
Normal file
1
system/clearpilot/tools_wip_4_28/remount_rw.sh
Normal file
@@ -0,0 +1 @@
|
||||
sudo mount -o remount,rw /
|
||||
33
system/clearpilot/tools_wip_4_28/rotation_module.cpp
Normal file
33
system/clearpilot/tools_wip_4_28/rotation_module.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <Python.h>
|
||||
#include <QGuiApplication>
|
||||
#include <QWidget>
|
||||
#include "/usr/include/aarch64-linux-gnu/qt5/QtGui/5.12.8/QtGui/qpa/qplatformnativeinterface.h"
|
||||
#include <wayland-client-protocol.h>
|
||||
|
||||
#include <QWindow>
|
||||
#include <sipAPIrotation.h>
|
||||
|
||||
static PyObject* rotate_display(PyObject* self, PyObject* args) {
|
||||
PyObject* pyObj;
|
||||
if (!PyArg_ParseTuple(args, "O", &pyObj))
|
||||
return NULL;
|
||||
|
||||
QWindow* window = sipUnwrapInstance<QWindow>(pyObj, sipAPI_rotation);
|
||||
if (!window) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid window object.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
|
||||
wl_surface *s = static_cast<wl_surface*>(native->nativeResourceForWindow("surface", window));
|
||||
if (!s) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Failed to obtain native Wayland surface.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270);
|
||||
wl_surface_commit(s);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
19
system/clearpilot/tools_wip_4_28/rotation_module.sip
Normal file
19
system/clearpilot/tools_wip_4_28/rotation_module.sip
Normal file
@@ -0,0 +1,19 @@
|
||||
// Define the module
|
||||
%Module rotation 0
|
||||
|
||||
// Import PyQt types
|
||||
%Import QtCore/QtCoremod.sip
|
||||
%Import QtGui/QtGuimod.sip
|
||||
|
||||
|
||||
// Define your class with the necessary methods
|
||||
class QWindow;
|
||||
|
||||
%MethodCode
|
||||
QWindow* window = reinterpret_cast<QWindow*>(a0);
|
||||
if (!window) {
|
||||
sipError = sipBadCallableArg;
|
||||
}
|
||||
%End
|
||||
|
||||
void rotate_display(QWindow *window);
|
||||
32
system/clearpilot/tools_wip_4_28/rotation_module_build.py
Normal file
32
system/clearpilot/tools_wip_4_28/rotation_module_build.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from setuptools import setup, Extension
|
||||
from distutils.command.build_ext import build_ext
|
||||
import os
|
||||
|
||||
# Specify the C++ compiler
|
||||
os.environ["CC"] = "clang++"
|
||||
os.environ["CXX"] = "clang++"
|
||||
|
||||
class BuildExt(build_ext):
|
||||
def build_extensions(self):
|
||||
c_opts = ['-std=c++1z', '-DQCOM2', '-mcpu=cortex-a57', '-Wno-deprecated-declarations', '-O2', '-Wunused', '-Werror', '-Wshadow']
|
||||
for e in self.extensions:
|
||||
e.extra_compile_args = c_opts
|
||||
build_ext.build_extensions(self)
|
||||
|
||||
module = Extension('rotation',
|
||||
sources=['rotation_module.cpp'],
|
||||
libraries=['Qt5Core', 'Qt5Gui', 'Qt5Widgets', 'wayland-client'],
|
||||
include_dirs=[
|
||||
'/usr/include/aarch64-linux-gnu/qt5',
|
||||
'/usr/include/aarch64-linux-gnu/qt5/QtCore',
|
||||
'/usr/include/aarch64-linux-gnu/qt5/QtGui',
|
||||
'/usr/include/aarch64-linux-gnu/qt5/QtWidgets'
|
||||
],
|
||||
library_dirs=['/usr/lib/aarch64-linux-gnu', '/lib/aarch64-linux-gnu'],
|
||||
language='c++')
|
||||
|
||||
setup(name='RotationModule',
|
||||
version='1.0',
|
||||
description='Module for rotating display via native interface',
|
||||
ext_modules=[module],
|
||||
cmdclass={'build_ext': BuildExt})
|
||||
@@ -0,0 +1,2 @@
|
||||
python3 rotation_module_build.py build
|
||||
cp build/lib.linux-aarch64-cpython-311/rotation.cpython-311-aarch64-linux-gnu.so ./rotation.so
|
||||
37
system/clearpilot/tools_wip_4_28/scrun
Normal file
37
system/clearpilot/tools_wip_4_28/scrun
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Usage:
|
||||
# scrun instancename command
|
||||
|
||||
# - If instancename doesnt exist, starts a screen with instancename and executes the given command.
|
||||
# - Does not run if the instance is already running.
|
||||
# - Runs in the same context as a shell (loads environment variables).
|
||||
# - Logs output into /var/log/scrun/instance/DATE.log, with rotation
|
||||
|
||||
# bash -l -c "$@"
|
||||
|
||||
# Based on https://gist.github.com/camperdave/980040
|
||||
echo "defshell -bash" > ~/.screenrc
|
||||
echo "startup_message off" >> ~/.screenrc
|
||||
echo "vbell off" >> ~/.screenrc
|
||||
echo "deflogin on" >> ~/.screenrc
|
||||
echo "defscrollback 10000" >> ~/.screenrc
|
||||
echo "defutf8 on" >> ~/.screenrc
|
||||
echo "defflow off" >> ~/.screenrc
|
||||
echo "msgwait 20" >> ~/.screenrc
|
||||
echo "term screen-256color-bce" >> ~/.screenrc
|
||||
|
||||
#SCREENNAME=scrun_$1_
|
||||
SCREENNAME=$1
|
||||
|
||||
screen -wipe 2>/dev/null >/dev/null
|
||||
|
||||
if ! screen -list | grep -q $SCREENNAME; then
|
||||
cesc="${@:2}" # Everything but first one
|
||||
# cesc="${cesc@Q}" # Escape it
|
||||
screen -dmS $SCREENNAME python3 /data/openpilot/system/clearpilot/tools/faketty.py bash -l -c "$cesc"
|
||||
echo screen -dmS $SCREENNAME python3 /data/openpilot/system/clearpilot/tools/faketty.py bash -l -c "$cesc"
|
||||
# screen -dmS $1 "$@"
|
||||
else
|
||||
echo $SCREENNAME is already running
|
||||
fi
|
||||
90
system/clearpilot/tools_wip_4_28/shell.py
Normal file
90
system/clearpilot/tools_wip_4_28/shell.py
Normal file
@@ -0,0 +1,90 @@
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
import logging
|
||||
import platform
|
||||
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QScrollBar, QGraphicsView, QGraphicsScene, QGraphicsProxyWidget
|
||||
from PyQt5.QtCore import Qt, QCoreApplication
|
||||
from PyQt5.QtGui import QFont, QScreen
|
||||
|
||||
import termqt
|
||||
from termqt import Terminal, TerminalPOSIXExecIO
|
||||
|
||||
class ExitOnMessageHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
if "Spawned process has been killed" in record.getMessage():
|
||||
QApplication.quit() # Exit the application gracefully
|
||||
|
||||
def setup_logger():
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.DEBUG)
|
||||
handler = logging.StreamHandler()
|
||||
formatter = logging.Formatter("[%(asctime)s] > [%(filename)s:%(lineno)d] %(message)s")
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
handler2 = ExitOnMessageHandler()
|
||||
logger.addHandler(handler2)
|
||||
return logger
|
||||
|
||||
def create_terminal_app():
|
||||
os.environ["XDG_RUNTIME_DIR"] = "/var/tmp/weston"
|
||||
os.environ["WAYLAND_DISPLAY"] = "wayland-0"
|
||||
os.environ["QT_QPA_PLATFORM"] = "wayland"
|
||||
os.environ["QT_WAYLAND_SHELL_INTEGRATION"] = "wl-shell"
|
||||
|
||||
|
||||
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
|
||||
app = QApplication(sys.argv)
|
||||
desktop = QApplication.desktop()
|
||||
ag = desktop.availableGeometry(desktop.primaryScreen())
|
||||
print (ag.width())
|
||||
print (ag.height())
|
||||
|
||||
window = QWidget()
|
||||
window.setWindowTitle("termqt on {}".format(platform.system()))
|
||||
window.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
||||
window.setGeometry(0,0, ag.width(), ag.height())
|
||||
window.setStyleSheet("background-color: black;")
|
||||
window.showFullScreen()
|
||||
|
||||
scene = QGraphicsScene()
|
||||
view = QGraphicsView(scene, window)
|
||||
print (window.width())
|
||||
print (window.height())
|
||||
view.setGeometry(0, 0, window.width(), window.height())
|
||||
view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
|
||||
layout = QHBoxLayout()
|
||||
terminal = Terminal(window.width(), window.height(), logger=setup_logger(), font_size=32)
|
||||
|
||||
proxy_terminal = scene.addWidget(terminal)
|
||||
view.setScene(scene)
|
||||
view.rotate(90) # Rotate the view by 90 degrees clockwise
|
||||
|
||||
window_layout = QHBoxLayout(window)
|
||||
window_layout.addWidget(view)
|
||||
window_layout.setContentsMargins(0,0,0,0)
|
||||
window.setLayout(window_layout)
|
||||
|
||||
return app, window, terminal
|
||||
|
||||
def main():
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL) # Enable Ctrl+C
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python start.py '<command>'")
|
||||
return
|
||||
|
||||
command = "bash -c '{}'".format(sys.argv[1])
|
||||
app, window, terminal = create_terminal_app()
|
||||
platform_name = platform.system()
|
||||
terminal_io = TerminalPOSIXExecIO(terminal.col_len, terminal.row_len, command, os.environ, setup_logger())
|
||||
terminal_io.stdout_callback = terminal.stdout
|
||||
terminal.stdin_callback = terminal_io.write
|
||||
terminal.resize_callback = terminal_io.resize
|
||||
terminal_io.spawn()
|
||||
exit_code = app.exec_()
|
||||
sys.exit(exit_code)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1
system/clearpilot/tools_wip_4_28/shell.sh
Normal file
1
system/clearpilot/tools_wip_4_28/shell.sh
Normal file
@@ -0,0 +1 @@
|
||||
sudo su comma -c "python3 shell.py \"echo hello; sleep 5\"
|
||||
28
system/clearpilot/tools_wip_4_28/test.c
Normal file
28
system/clearpilot/tools_wip_4_28/test.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void activate(GtkApplication* app, gpointer user_data) {
|
||||
GtkWidget *window;
|
||||
window = gtk_application_window_new(app);
|
||||
gtk_window_set_title(GTK_WINDOW(window), "Basic C GTK App");
|
||||
gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
|
||||
gtk_widget_show_all(window);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
GtkApplication *app;
|
||||
int status;
|
||||
|
||||
// Signal handling
|
||||
signal(SIGINT, SIG_DFL);
|
||||
|
||||
app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE);
|
||||
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
|
||||
status = g_application_run(G_APPLICATION(app), argc, argv);
|
||||
g_object_unref(app);
|
||||
|
||||
return status;
|
||||
}
|
||||
BIN
system/clearpilot/tools_wip_4_28/test2
Executable file
BIN
system/clearpilot/tools_wip_4_28/test2
Executable file
Binary file not shown.
62
system/clearpilot/tools_wip_4_28/test2.cc
Normal file
62
system/clearpilot/tools_wip_4_28/test2.cc
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <QApplication>
|
||||
#include <QWebView>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <QtWebKit>
|
||||
#include <QtWebKitWidgets>
|
||||
|
||||
#include "/data/openpilot/system/hardware/hw.h"
|
||||
#include "/data/openpilot/selfdrive/ui/qt/qt_window.h"
|
||||
#include "/data/openpilot/selfdrive/ui/qt/util.h"
|
||||
|
||||
static void handleSignal(int sig) {
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s <url>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set up Ctrl+C signal handler
|
||||
signal(SIGINT, handleSignal);
|
||||
|
||||
QWidget window;
|
||||
window.setWindowTitle("Web Viewer");
|
||||
window.setStyleSheet("background-color: black;");
|
||||
window.showFullScreen(); // Show the window to ensure the handle is valid
|
||||
|
||||
auto windowHandle = window.windowHandle();
|
||||
if (!windowHandle) {
|
||||
fprintf(stderr, "Error: Unable to obtain window handle.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
|
||||
auto *s = static_cast<wl_surface*>(native->nativeResourceForWindow("surface", windowHandle));
|
||||
if (!s) {
|
||||
fprintf(stderr, "Error: Unable to obtain native Wayland surface.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270);
|
||||
wl_surface_commit(s);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(&window);
|
||||
QWebView *view = new QWebView;
|
||||
view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // Ensure it expands to fill layout
|
||||
layout->addWidget(view);
|
||||
|
||||
QString url = argv[1];
|
||||
view->load(QUrl(url));
|
||||
|
||||
// Resize window after setting up layout and loading the page
|
||||
window.setFixedSize(2160, 1080); // Set fixed size after rotation
|
||||
|
||||
window.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
10
system/clearpilot/tools_wip_4_28/test2.h
Normal file
10
system/clearpilot/tools_wip_4_28/test2.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <array>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPixmap>
|
||||
#include <QProgressBar>
|
||||
#include <QSocketNotifier>
|
||||
#include <QVariantAnimation>
|
||||
#include <QWidget>
|
||||
|
||||
#include <QConsole.h>
|
||||
120
system/clearpilot/tools_wip_4_28/test3.cc
Normal file
120
system/clearpilot/tools_wip_4_28/test3.cc
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "test2.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QGridLayout>
|
||||
#include <QPainter>
|
||||
#include <QString>
|
||||
#include <QTransform>
|
||||
|
||||
#include "/data/openpilot/system/hardware/hw.h"
|
||||
#include "/data/openpilot/selfdrive/ui/qt/qt_window.h"
|
||||
#include "/data/openpilot/selfdrive/ui/qt/util.h"
|
||||
|
||||
TrackWidget::TrackWidget(QWidget *parent) : QWidget(parent) {
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
setFixedSize(spinner_size);
|
||||
|
||||
// pre-compute all the track imgs. make this a gif instead?
|
||||
QPixmap comma_img = loadPixmap("../assets/img_spinner_comma.png", spinner_size);
|
||||
QPixmap track_img = loadPixmap("../assets/img_spinner_track.png", spinner_size);
|
||||
|
||||
QTransform transform(1, 0, 0, 1, width() / 2, height() / 2);
|
||||
QPixmap pm(spinner_size);
|
||||
QPainter p(&pm);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
for (int i = 0; i < track_imgs.size(); ++i) {
|
||||
p.resetTransform();
|
||||
p.fillRect(0, 0, spinner_size.width(), spinner_size.height(), Qt::black);
|
||||
p.drawPixmap(0, 0, comma_img);
|
||||
p.setTransform(transform.rotate(360 / spinner_fps));
|
||||
p.drawPixmap(-width() / 2, -height() / 2, track_img);
|
||||
track_imgs[i] = pm.copy();
|
||||
}
|
||||
|
||||
m_anim.setDuration(1000);
|
||||
m_anim.setStartValue(0);
|
||||
m_anim.setEndValue(int(track_imgs.size() -1));
|
||||
m_anim.setLoopCount(-1);
|
||||
m_anim.start();
|
||||
connect(&m_anim, SIGNAL(valueChanged(QVariant)), SLOT(update()));
|
||||
}
|
||||
|
||||
void TrackWidget::paintEvent(QPaintEvent *event) {
|
||||
QPainter painter(this);
|
||||
painter.drawPixmap(0, 0, track_imgs[m_anim.currentValue().toInt()]);
|
||||
}
|
||||
|
||||
// Spinner
|
||||
|
||||
Spinner::Spinner(QWidget *parent) : QWidget(parent) {
|
||||
QGridLayout *main_layout = new QGridLayout(this);
|
||||
main_layout->setSpacing(0);
|
||||
main_layout->setMargin(200);
|
||||
|
||||
main_layout->addWidget(new TrackWidget(this), 0, 0, Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
text = new QLabel();
|
||||
text->setWordWrap(true);
|
||||
text->setVisible(false);
|
||||
text->setAlignment(Qt::AlignCenter);
|
||||
main_layout->addWidget(text, 1, 0, Qt::AlignHCenter);
|
||||
|
||||
progress_bar = new QProgressBar();
|
||||
progress_bar->setRange(5, 100);
|
||||
progress_bar->setTextVisible(false);
|
||||
progress_bar->setVisible(false);
|
||||
progress_bar->setFixedHeight(20);
|
||||
main_layout->addWidget(progress_bar, 1, 0, Qt::AlignHCenter);
|
||||
|
||||
setStyleSheet(R"(
|
||||
Spinner {
|
||||
background-color: black;
|
||||
}
|
||||
QLabel {
|
||||
color: white;
|
||||
font-size: 80px;
|
||||
background-color: transparent;
|
||||
}
|
||||
QProgressBar {
|
||||
background-color: #373737;
|
||||
width: 1000px;
|
||||
border solid white;
|
||||
border-radius: 10px;
|
||||
}
|
||||
QProgressBar::chunk {
|
||||
border-radius: 10px;
|
||||
background-color: rgba(23, 134, 68, 255);
|
||||
}
|
||||
)");
|
||||
|
||||
notifier = new QSocketNotifier(fileno(stdin), QSocketNotifier::Read);
|
||||
QObject::connect(notifier, &QSocketNotifier::activated, this, &Spinner::update);
|
||||
}
|
||||
|
||||
void Spinner::update(int n) {
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
|
||||
if (line.length()) {
|
||||
bool number = std::all_of(line.begin(), line.end(), ::isdigit);
|
||||
text->setVisible(!number);
|
||||
progress_bar->setVisible(number);
|
||||
text->setText(QString::fromStdString(line));
|
||||
if (number) {
|
||||
progress_bar->setValue(std::stoi(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
initApp(argc, argv);
|
||||
QApplication a(argc, argv);
|
||||
Spinner spinner;
|
||||
setMainWindow(&spinner);
|
||||
return a.exec();
|
||||
}
|
||||
37
system/clearpilot/tools_wip_4_28/test3.h
Normal file
37
system/clearpilot/tools_wip_4_28/test3.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <array>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPixmap>
|
||||
#include <QProgressBar>
|
||||
#include <QSocketNotifier>
|
||||
#include <QVariantAnimation>
|
||||
#include <QWidget>
|
||||
|
||||
constexpr int spinner_fps = 30;
|
||||
constexpr QSize spinner_size = QSize(360, 360);
|
||||
|
||||
class TrackWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackWidget(QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
std::array<QPixmap, spinner_fps> track_imgs;
|
||||
QVariantAnimation m_anim;
|
||||
};
|
||||
|
||||
class Spinner : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Spinner(QWidget *parent = 0);
|
||||
|
||||
private:
|
||||
QLabel *text;
|
||||
QProgressBar *progress_bar;
|
||||
QSocketNotifier *notifier;
|
||||
|
||||
public slots:
|
||||
void update(int n);
|
||||
};
|
||||
64
system/clearpilot/tools_wip_4_28/test4.cc
Normal file
64
system/clearpilot/tools_wip_4_28/test4.cc
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
#include <QTextEdit>
|
||||
#include <QProcess>
|
||||
#include <QVBoxLayout>
|
||||
#include <QString>
|
||||
#include <QFont>
|
||||
#include <QScreen>
|
||||
#include <QScrollBar>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#include <wayland-client-protocol.h>
|
||||
#include <QPlatformSurfaceEvent>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s '<command>'\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
QWidget window;
|
||||
window.setWindowTitle("Shell Command Output Viewer");
|
||||
window.setStyleSheet("background-color: black;");
|
||||
|
||||
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
|
||||
wl_surface *s = reinterpret_cast<wl_surface*>(native->nativeResourceForWindow("surface", window.windowHandle()));
|
||||
wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270);
|
||||
wl_surface_commit(s);
|
||||
void *egl = native->nativeResourceForWindow("egldisplay", window.windowHandle());
|
||||
assert(egl != nullptr);
|
||||
|
||||
window.showFullScreen();
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(&window);
|
||||
QTextEdit *outputDisplay = new QTextEdit;
|
||||
outputDisplay->setFont(QFont("Consolas", 32));
|
||||
outputDisplay->setReadOnly(true);
|
||||
outputDisplay->setStyleSheet("color: white; background-color: black;");
|
||||
layout->addWidget(outputDisplay);
|
||||
|
||||
QProcess process;
|
||||
QObject::connect(&process, &QProcess::readyReadStandardOutput, [&]() {
|
||||
static QStringList lines;
|
||||
QString output = process.readAllStandardOutput();
|
||||
lines += output.split("\n", QString::SkipEmptyParts);
|
||||
while (lines.size() > 100) {
|
||||
lines.removeFirst();
|
||||
}
|
||||
outputDisplay->setPlainText(lines.join("\n"));
|
||||
outputDisplay->verticalScrollBar()->setValue(outputDisplay->verticalScrollBar()->maximum());
|
||||
});
|
||||
|
||||
QObject::connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [&]() {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
QString command = argv[1];
|
||||
process.start(QString("bash -c \"%1\"").arg(command));
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
66
system/clearpilot/tools_wip_4_28/webview.py
Normal file
66
system/clearpilot/tools_wip_4_28/webview.py
Normal file
@@ -0,0 +1,66 @@
|
||||
import os
|
||||
import sys
|
||||
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QGraphicsView, QGraphicsScene
|
||||
from PyQt5.QtCore import Qt, QUrl, QTimer
|
||||
from PyQt5.QtGui import QCursor, QPixmap, QTransform
|
||||
from PyQt5.QtWebEngineWidgets import QWebEngineView
|
||||
import rotation
|
||||
|
||||
def create_webview_app():
|
||||
# Set environment for Wayland
|
||||
os.environ["XDG_RUNTIME_DIR"] = "/var/tmp/weston"
|
||||
os.environ["WAYLAND_DISPLAY"] = "wayland-0"
|
||||
os.environ["QT_QPA_PLATFORM"] = "wayland"
|
||||
os.environ["QT_WAYLAND_SHELL_INTEGRATION"] = "wl-shell"
|
||||
|
||||
# Application setup
|
||||
app = QApplication(sys.argv)
|
||||
window = QWidget()
|
||||
window.setWindowTitle("Qt WebView Example")
|
||||
window.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
||||
sg = QApplication.desktop().availableGeometry(window)
|
||||
window.setGeometry(0, 0, sg.height(), sg.width())
|
||||
window.setStyleSheet("background-color: black;")
|
||||
|
||||
scene = QGraphicsScene()
|
||||
view = QGraphicsView(scene, window)
|
||||
view.setGeometry(0, 0, sg.width(), sg.height())
|
||||
view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
|
||||
webview = QWebEngineView()
|
||||
webview.load(QUrl("https://cdpn.io/yananas/fullpage/rwvZvY"))
|
||||
webview.setGeometry(0, 0, sg.width(), sg.height())
|
||||
scene.addWidget(webview)
|
||||
view.setScene(scene)
|
||||
|
||||
window_layout = QHBoxLayout(window)
|
||||
window_layout.addWidget(view)
|
||||
|
||||
window.setLayout(window_layout)
|
||||
|
||||
window.showFullScreen()
|
||||
|
||||
window_handle = window.windowHandle()
|
||||
rotation.rotate_display(window_handle)
|
||||
|
||||
# Delay rotation using QTimer
|
||||
# QTimer.singleShot(1000, lambda: rotate_display(window))
|
||||
|
||||
return app, window
|
||||
|
||||
def rotate_display(window):
|
||||
window_handle = window.windowHandle()
|
||||
if window_handle:
|
||||
print("Rotating display.")
|
||||
try:
|
||||
print(int(window_handle.winId()))
|
||||
rotation.rotate_display(int(window_handle.winId()))
|
||||
except Exception as e:
|
||||
print(f"Error rotating display: {e}")
|
||||
else:
|
||||
print("Window handle is not valid.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
app, _ = create_webview_app()
|
||||
sys.exit(app.exec_())
|
||||
1
system/clearpilot/tools_wip_4_28/webview.sh
Normal file
1
system/clearpilot/tools_wip_4_28/webview.sh
Normal file
@@ -0,0 +1 @@
|
||||
sudo su comma -c "nice python3 webview.py"
|
||||
75
system/clearpilot/tools_wip_4_28/webview2.py
Normal file
75
system/clearpilot/tools_wip_4_28/webview2.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QGraphicsView, QGraphicsScene
|
||||
from PyQt5.QtCore import Qt, QUrl, QPointF, QTimer, QObject, QEvent
|
||||
from PyQt5.QtGui import QCursor, QPixmap, QTransform
|
||||
from PyQt5.QtWebEngineWidgets import QWebEngineView
|
||||
|
||||
import rotation
|
||||
|
||||
webview = None
|
||||
|
||||
def create_webview_app():
|
||||
global webview
|
||||
|
||||
# Set environment for Wayland
|
||||
os.environ["XDG_RUNTIME_DIR"] = "/var/tmp/weston"
|
||||
os.environ["WAYLAND_DISPLAY"] = "wayland-0"
|
||||
os.environ["QT_QPA_PLATFORM"] = "wayland"
|
||||
os.environ["QT_WAYLAND_SHELL_INTEGRATION"] = "wl-shell"
|
||||
|
||||
# Application setup
|
||||
app = QApplication(sys.argv)
|
||||
desktop = QApplication.desktop()
|
||||
|
||||
sg = desktop.availableGeometry(desktop.primaryScreen())
|
||||
|
||||
window = QWidget()
|
||||
window.setWindowTitle("Qt WebView Example")
|
||||
window.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
||||
window.setGeometry(0, 0, sg.height(), sg.width())
|
||||
window.setStyleSheet("background-color: black;")
|
||||
window.showFullScreen()
|
||||
|
||||
scene = QGraphicsScene()
|
||||
view = QGraphicsView(scene, window)
|
||||
view.setGeometry(0, 0, sg.width(), sg.height())
|
||||
view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
|
||||
# Create WebView
|
||||
webview = QWebEngineView()
|
||||
webview.load(QUrl("https://cdpn.io/yananas/fullpage/rwvZvY"))
|
||||
webview.setGeometry(0, 0, sg.width(), sg.height())
|
||||
|
||||
# Add WebView to the scene
|
||||
proxy_webview = scene.addWidget(webview)
|
||||
view.setScene(scene)
|
||||
# view.rotate(90) # Rotate the view by 90 degrees
|
||||
|
||||
# Layout setup
|
||||
window_layout = QHBoxLayout(window)
|
||||
window_layout.addWidget(view)
|
||||
window_layout.setContentsMargins(0, 0, 0, 0)
|
||||
window.setLayout(window_layout)
|
||||
|
||||
window_handle = int(window.winId())
|
||||
# window_handle = window.windowHandle()
|
||||
print ("Handle:")
|
||||
print (window_handle)
|
||||
# if window_handle:
|
||||
# rotation.rotate_display(window_handle)
|
||||
# else:
|
||||
# print("Window handle is not valid.")
|
||||
|
||||
return app, window
|
||||
|
||||
def main():
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL) # Enable Ctrl+C to terminate the application
|
||||
app, window = create_webview_app()
|
||||
exit_code = app.exec_()
|
||||
sys.exit(exit_code)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user