assistant.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. ktigcc - TIGCC IDE for KDE
  3. Copyright (C) 2006 Kevin Kofler
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software Foundation,
  14. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. // This class is like QAssistantClient, but simpler (taylored to KTIGCC's use)
  17. // and uses KProcess and KExtendedSocket instead of QProcess and QSocket. This
  18. // is needed because, very annoyingly, QProcess doesn't work together with
  19. // KProcess.
  20. #include "assistant.h"
  21. #include <kprocio.h>
  22. #include <kextsock.h>
  23. #include <kmessagebox.h>
  24. #include <qtextcodec.h>
  25. #include <qwidget.h>
  26. #include <qapplication.h>
  27. #include <qeventloop.h>
  28. #include <qtextstream.h>
  29. #include <unistd.h>
  30. AssistantClient::AssistantClient(QObject *parent, const QString &profile)
  31. : QObject(parent), parentWidget(0), procIO(0), socket(0),
  32. assistantProfile(profile)
  33. {
  34. if (parent->isWidgetType()) parentWidget=static_cast<QWidget *>(parent);
  35. }
  36. AssistantClient::~AssistantClient()
  37. {
  38. int socketStatus=socket?socket->socketStatus():0;
  39. if (socketStatus && socketStatus<KExtendedSocket::lookupInProgress) {
  40. KMessageBox::error(parentWidget,socket->strError(socketStatus,
  41. socket->systemError()),
  42. "Socket Error");
  43. }
  44. if (procIO) {
  45. procIO->kill();
  46. usleep(100000);
  47. delete procIO;
  48. }
  49. if (socket) delete socket;
  50. }
  51. void AssistantClient::openAssistant(const QString &page)
  52. {
  53. int socketStatus=socket?socket->socketStatus():0;
  54. if (socketStatus && socketStatus<KExtendedSocket::lookupInProgress) {
  55. KMessageBox::error(parentWidget,socket->strError(socketStatus,
  56. socket->systemError()),
  57. "Socket Error");
  58. procIO->kill();
  59. usleep(100000);
  60. delete procIO;
  61. procIO=static_cast<KProcIO *>(NULL);
  62. return;
  63. }
  64. if (socketStatus>=KExtendedSocket::closing) {
  65. // The old process is not closed yet, but the connection was already lost.
  66. // So kill the old process now and run a new one.
  67. procIO->kill();
  68. usleep(100000);
  69. delete procIO;
  70. procIO=static_cast<KProcIO *>(NULL);
  71. delete socket;
  72. socket=static_cast<KExtendedSocket *>(NULL);
  73. }
  74. if (!procIO) {
  75. start_new:
  76. // The QTextCodec has to be passed explicitly, or it will default to
  77. // ISO-8859-1 regardless of the locale, which is just broken.
  78. procIO=new KProcIO(QTextCodec::codecForLocale());
  79. // Use MergedStderr instead of Stderr so the messages get ordered
  80. // properly.
  81. procIO->setComm(static_cast<KProcess::Communication>(
  82. KProcess::Stdout|KProcess::MergedStderr));
  83. (*procIO)<<"assistant"<<"-server";
  84. if (!assistantProfile.isNull())
  85. (*procIO)<<"-profile"<<assistantProfile;
  86. if (!page.isNull())
  87. (*procIO)<<"-file"<<page;
  88. connect(procIO,SIGNAL(processExited(KProcess*)),
  89. this,SLOT(procIO_processExited()));
  90. connect(procIO,SIGNAL(readReady(KProcIO*)),this,SLOT(procIO_readReady()));
  91. if (!procIO->start()) {
  92. KMessageBox::error(parentWidget,"Could not run assistant.\n"
  93. "This feature requires Qt 3 Assistant.");
  94. delete procIO;
  95. procIO=static_cast<KProcIO *>(NULL);
  96. return;
  97. }
  98. } else if (!page.isNull()) {
  99. // Wait for Qt Assistant to actually open.
  100. while (procIO && !socket) {
  101. usleep(10000);
  102. QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput,10);
  103. }
  104. if (!procIO) goto start_new;
  105. QTextStream stream(static_cast<QIODevice *>(socket));
  106. stream<<page<<'\n';
  107. }
  108. }
  109. void AssistantClient::procIO_processExited()
  110. {
  111. disconnect(procIO,SIGNAL(processExited(KProcess*)),
  112. this,SLOT(procIO_processExited()));
  113. disconnect(procIO,SIGNAL(readReady(KProcIO*)),this,SLOT(procIO_readReady()));
  114. procIO->deleteLater();
  115. procIO=static_cast<KProcIO *>(NULL);
  116. int socketStatus=socket?socket->socketStatus():0;
  117. if (socketStatus && socketStatus<KExtendedSocket::lookupInProgress) {
  118. KMessageBox::error(parentWidget,socket->strError(socketStatus,
  119. socket->systemError()),
  120. "Socket Error");
  121. }
  122. if (socket) delete socket;
  123. socket=static_cast<KExtendedSocket *>(NULL);
  124. }
  125. void AssistantClient::procIO_readReady()
  126. {
  127. QString line;
  128. while (procIO->readln(line)>=0) {
  129. if (!socket) {
  130. bool ok;
  131. unsigned short port=line.toUShort(&ok);
  132. if (ok) {
  133. socket=new KExtendedSocket("localhost",port,KExtendedSocket::inetSocket);
  134. switch (socket->connect()) {
  135. case 0:
  136. break;
  137. case -1:
  138. KMessageBox::error(parentWidget,socket->strError(socket->socketStatus(),
  139. socket->systemError()),
  140. "Socket Error");
  141. goto error;
  142. case -2:
  143. KMessageBox::error(parentWidget,"Failed to connect to Qt Assistant.",
  144. "Socket Error");
  145. goto error;
  146. case -3:
  147. KMessageBox::error(parentWidget,"Connection to Qt Assistant timed out.",
  148. "Socket Error");
  149. goto error;
  150. default:
  151. KMessageBox::error(parentWidget,"Socket Error.");
  152. error:
  153. disconnect(procIO,SIGNAL(processExited(KProcess*)),
  154. this,SLOT(procIO_processExited()));
  155. disconnect(procIO,SIGNAL(readReady(KProcIO*)),
  156. this,SLOT(procIO_readReady()));
  157. procIO->kill();
  158. usleep(100000);
  159. procIO->deleteLater();
  160. procIO=static_cast<KProcIO *>(NULL);
  161. delete socket;
  162. socket=static_cast<KExtendedSocket *>(NULL);
  163. return;
  164. }
  165. continue;
  166. }
  167. }
  168. KMessageBox::error(parentWidget,line,"Qt Assistant Error");
  169. }
  170. }