コード例 #1
0
void KstJS::showConsole() {
#ifdef KST_HAVE_READLINE
  if (!_konsolePart) {
    strcpy(shellStr, "SHELL=kstcmd");
    putenv(shellStr);
    KLibFactory *f = KLibLoader::self()->factory("libkonsolepart");
    if (!f) {
      KMessageBox::sorry(app(), i18n("Could not load konsole part.  Please install kdebase."));
      _showAction->setChecked(false);
      return;
    }

    if (!_splitter) {
      _splitter = new QSplitter(Qt::Vertical, app());
      _oldCentralWidget = app()->centralWidget();
      _oldCentralWidget->reparent(_splitter, QPoint(0, 0));
      _splitter->show();
      app()->setCentralWidget(_splitter);
    }

    KParts::Part *p = dynamic_cast<KParts::Part*>(f->create(_splitter, "kstcmd"));
    if (!p) {
      KMessageBox::sorry(app(), i18n("Konsole part appears to be incompatible.  Please install kdebase correctly."));
      _showAction->setChecked(false);
      return;
    }

    _splitter->moveToLast(p->widget());
    connect(p, SIGNAL(destroyed()), this, SLOT(shellExited()));
    _konsolePart = p;
  }

  _konsolePart->widget()->show();
#endif
}
コード例 #2
0
ファイル: qterminal_pty.cpp プロジェクト: spthaolt/qscite
QTerminal::QTerminal(QWidget *parent, Qt::WindowFlags f) : QTextEdit(parent) {
  setWindowFlags(f);
  qDebug() << "Constructing QTerminal";
  savedCursor = this->textCursor();
  sequenceState = NoSequence;
  insertMode = false;

  // The Following line causes the tab key to change focus...
  //setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
  //

  //setTabChangesFocus(false);
  //setFocusPolicy(Qt::ClickFocus);

  /*
   * Launch a shell connected to the current process by a PTY
   */
  shellPid = forkpty(&fdMaster, NULL, NULL, NULL);
  if (0 == shellPid) { /* fork off a shell */
    /* if they don't have a shell, use bash */
    setenv("SHELL", "/bin/bash", 0);
    /* no special control features are supported */
    setenv("TERM", "xterm", 1);
    /* hand off to the shell of choice */
    execl(getenv("SHELL"), getenv("SHELL"), (char *)0);
    /* If this exec returns, we should take some action.
     * Window systems do ugly things if two processes try
     * to use the same resources. */
    if (errno == ENOENT) {
      execl("/bin/sh", "/bin/sh", (char*)0);
    }
    perror("QTerminal: exec");
     // exit hard in case exit handlers mess with the window system
     _exit(127);
  } else if (-1 == shellPid) { // didn't fork
    this->setText(QString("QTerminal: fork: %1\n").arg(strerror(errno)));
  } else {

    /*
     * We will use non-blocking I/O to read from the shell
     */
    fcntl(fdMaster, F_SETFL, fcntl(fdMaster, F_GETFL, 0) | O_NONBLOCK);
    qDebug() << "Shell PID " << shellPid << " on file descriptor " << fdMaster;

    /*
     * Arrange to be notified when the shell emits output
     */
    watcher = new FileDescriptorMonitor(fdMaster, this);
    connect(watcher, SIGNAL(readyForRead(int)), this, SLOT(readOutput()), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(shellExited()), watcher, SLOT(stop()));
    watcher->start();
  }
}
コード例 #3
0
void MainWindow::toggleTerminal(bool alive) {
  if (alive) { // we were called by a dock window reporting itself visible
    return;
  }
  QSettings settings;

  if (termWidget != NULL) {
    if (!termInDrawer) {
      termWidget->parent()->deleteLater();
    }

    qDebug() << "Closing terminal";
    termWidget->disconnect();
    termWidget->deleteLater();
    termWidget = NULL;

    if (openFiles.size() > 0) {
      getCurDoc()->setFocus();
    }

    copyFromTerm = false;
  } else {
    qDebug() << "Opening terminal";
    termWidget = new QTerminal(this);
    applyPrefsToTerminal(termWidget);
    if (openFiles.size() > 0 && !getCurFileObj()->fullName.isEmpty()) {
    	termWidget->changeDir(getCurFileObj()->path);
    }

    if (termInDrawer) {
      termWidget->setWindowFlags(Qt::Drawer);
      termWidget->show();
    } else {
      QDockWidget * termDock = new QDockWidget(tr("QSciTE Terminal"), this);
      termDock->setWidget(termWidget);
      termDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
      this->addDockWidget(Qt::BottomDockWidgetArea, termDock);
    }

    connect(termWidget, SIGNAL(shellExited()), this, SLOT(toggleTerminal()));
    connect(termWidget, SIGNAL(copyAvailable(bool)), this, SLOT(updateCopyAvailable(bool)));
    termWidget->setFocus();
    copyFromTerm = true;
  }
}
コード例 #4
0
ファイル: qterminal_pty.cpp プロジェクト: spthaolt/qscite
void QTerminal::readOutput() {
  this->setTextCursor(savedCursor);
  
  char rdBuf[256];
  ssize_t count = read(fdMaster, rdBuf, sizeof(rdBuf)/sizeof(char));
  
  if (0 == count || (-1 == count && errno == EIO)) { // EOF, child closed
    watcher->stop();
    watcher->disconnect();
    int childStatus;
    pid_t waitedPid = waitpid(shellPid, &childStatus, 0);
    if (waitedPid == shellPid) {
      shellPid = 0;
      if (WIFEXITED(childStatus)) {
        if(WEXITSTATUS(childStatus) == 0) {
          emit shellExited();
        } else {
          this->insertPlainText(QString("%1 exited with status %2.\n").arg(waitedPid).arg(WEXITSTATUS(childStatus)));
        }
      } else if (WIFSIGNALED(childStatus)) {
        this->insertPlainText(QString("%1 exited with signal %2.\n").arg(waitedPid).arg(WTERMSIG(childStatus)));
      } else {
        this->insertPlainText("QTerminal: Why are WIFEXITED and WIFSIGNALED both false?\n");
      }
      return;
    } else {
      perror("QTerminal: waitpid");
    }
  }
  if ((-1 == count) && (errno != EAGAIN)) {
    perror("QTerminal: read");
    return;
  }

  for (char * c = rdBuf; c < rdBuf + count; ++c) {
    switch (sequenceState) {
      case GotEsc:
        if (*c == '[') {
          sequenceState = InCS;
        } else if (*c == ']') {
          sequenceState = InOSC;
        } else {
          qWarning("No Can Do ESC %c", *c);
          sequenceState = NoSequence;
        }
        break;
      case InCS:
        if (*c >= '\x20' && *c <= '\x7e') {
          savedSequence += *c;
          if (*c >= '\x40') {
            doControlSeq(savedSequence);
            savedSequence.clear();
            sequenceState = NoSequence;
          }
        } else {
          /* ANSI says control or high-half bytes shouldn't happen
           * inside a control sequence. ANSI didn't write every program
           * in existence.
           */
          qWarning("No Can Do Esc [ %s", savedSequence.toHex().constData());
          savedSequence.clear();
          sequenceState = NoSequence;
        }
        break;
      case InOSC:
        savedSequence += *c;
        if (*c  == '\x07') {
          doOSCommand(savedSequence);
          savedSequence.clear();
          sequenceState = NoSequence;
        } else if (*c == '\x1b') {
          sequenceState = OSCHalfClosed;
        }
        break;
      case OSCHalfClosed:
        savedSequence += *c;
        if (*c == '\\') {
          doOSCommand(savedSequence);
        } else {
          qWarning("No Can Do Esc ] %s", savedSequence.toHex().constData());
        }
        savedSequence.clear();
        sequenceState = NoSequence;
        break;
      default:
        qWarning("QTerminal::sequenceState got set to %d", sequenceState);
        sequenceState = NoSequence;
        // FALL THROUGH
      case NoSequence:
        switch (*c) {
          case '\x1b':
            /* ASCII ESC. */
            if (!savedSequence.isEmpty()) {
              this->insertPlainText(savedSequence);
              savedSequence.clear();
            }
            sequenceState = GotEsc;
            break;
          case '\r':
            if (!savedSequence.isEmpty()) {
              this->insertPlainText(savedSequence);
              savedSequence.clear();
            }
            {
              QTextCursor cursor = this->textCursor();
              cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
              this->setTextCursor(cursor);
            }
            break;
          case '\x08':
            /* Backspace. We assume non-destructive. */
            if (!savedSequence.isEmpty()) {
              this->insertPlainText(savedSequence);
              savedSequence.clear();
            }
            this->moveCursor(QTextCursor::PreviousCharacter);
            break;
          case '\a':
            /* ASCII BEL. */
            QApplication::beep();
            break;
          case '\n':
            if (!savedSequence.isEmpty()) {
              this->insertPlainText(savedSequence);
              savedSequence.clear();
            }
            {
              QTextCursor csr = this->textCursor();
              QTextCursor tcStart = this->textCursor();
              tcStart.movePosition(QTextCursor::StartOfBlock);
              int col = csr.position() - tcStart.position();
              if (!csr.movePosition(QTextCursor::NextBlock)) {
                csr.movePosition(QTextCursor::EndOfBlock);
                csr.insertText(QString("\n") + QString().fill(' ', col));
              } else {
                if (!csr.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, col)) {
                  tcStart = csr;
                  tcStart.movePosition(QTextCursor::StartOfBlock);
                  int curCol = csr.position() - tcStart.position();
                  csr.insertText(QString().fill(' ', col - curCol));
                }
              }
              this->setTextCursor(csr);
            }
            break;
          default:
            if (!(this->textCursor().atEnd()) && !insertMode) {
              this->textCursor().deleteChar();
              this->insertPlainText(QChar(*c));
            } else {
              savedSequence += *c;
            }
            break;
        }
        break;
    }
  }
  if (sequenceState == NoSequence && !savedSequence.isEmpty()) {
    this->insertPlainText(savedSequence);
    savedSequence.clear();
  }
  savedCursor = this->textCursor();
  ensureCursorVisible();
}