assistant.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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) delete procIO;
  45. if (socket) delete socket;
  46. }
  47. void AssistantClient::openAssistant(const QString &page)
  48. {
  49. int socketStatus=socket?socket->socketStatus():0;
  50. if (socketStatus && socketStatus<KExtendedSocket::lookupInProgress) {
  51. KMessageBox::error(parentWidget,socket->strError(socketStatus,
  52. socket->systemError()),
  53. "Socket Error");
  54. delete procIO;
  55. procIO=static_cast<KProcIO *>(NULL);
  56. return;
  57. }
  58. if (socketStatus>=KExtendedSocket::closing) {
  59. // The old process is not closed yet, but the connection was already lost.
  60. // So kill the old process now and run a new one.
  61. delete procIO;
  62. procIO=static_cast<KProcIO *>(NULL);
  63. delete socket;
  64. socket=static_cast<KExtendedSocket *>(NULL);
  65. }
  66. if (!procIO) {
  67. start_new:
  68. // The QTextCodec has to be passed explicitly, or it will default to
  69. // ISO-8859-1 regardless of the locale, which is just broken.
  70. procIO=new KProcIO(QTextCodec::codecForLocale());
  71. // Use MergedStderr instead of Stderr so the messages get ordered
  72. // properly.
  73. procIO->setComm(static_cast<KProcess::Communication>(
  74. KProcess::Stdout|KProcess::MergedStderr));
  75. (*procIO)<<"assistant"<<"-server";
  76. if (!assistantProfile.isNull())
  77. (*procIO)<<"-profile"<<assistantProfile;
  78. if (!page.isNull())
  79. (*procIO)<<"-file"<<page;
  80. connect(procIO,SIGNAL(processExited(KProcess*)),
  81. this,SLOT(procIO_processExited()));
  82. connect(procIO,SIGNAL(readReady(KProcIO*)),this,SLOT(procIO_readReady()));
  83. if (!procIO->start()) {
  84. KMessageBox::error(parentWidget,"Could not run assistant.\n"
  85. "This feature requires Qt 3 Assistant.");
  86. delete procIO;
  87. procIO=static_cast<KProcIO *>(NULL);
  88. return;
  89. }
  90. } else if (!page.isNull()) {
  91. // Wait for Qt Assistant to actually open.
  92. while (procIO && !socket) {
  93. usleep(10000);
  94. QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput,10);
  95. }
  96. if (!procIO) goto start_new;
  97. QTextStream stream(static_cast<QIODevice *>(socket));
  98. stream<<page<<'\n';
  99. }
  100. }
  101. void AssistantClient::procIO_processExited()
  102. {
  103. disconnect(procIO,SIGNAL(processExited(KProcess*)),
  104. this,SLOT(procIO_processExited()));
  105. disconnect(procIO,SIGNAL(readReady(KProcIO*)),this,SLOT(procIO_readReady()));
  106. procIO->deleteLater();
  107. procIO=static_cast<KProcIO *>(NULL);
  108. int socketStatus=socket?socket->socketStatus():0;
  109. if (socketStatus && socketStatus<KExtendedSocket::lookupInProgress) {
  110. KMessageBox::error(parentWidget,socket->strError(socketStatus,
  111. socket->systemError()),
  112. "Socket Error");
  113. }
  114. if (socket) delete socket;
  115. socket=static_cast<KExtendedSocket *>(NULL);
  116. }
  117. void AssistantClient::procIO_readReady()
  118. {
  119. QString line;
  120. while (procIO->readln(line)>=0) {
  121. if (!socket) {
  122. bool ok;
  123. unsigned short port=line.toUShort(&ok);
  124. if (ok) {
  125. socket=new KExtendedSocket("localhost",port,KExtendedSocket::inetSocket);
  126. switch (socket->connect()) {
  127. case 0:
  128. break;
  129. case -1:
  130. KMessageBox::error(parentWidget,socket->strError(socket->socketStatus(),
  131. socket->systemError()),
  132. "Socket Error");
  133. goto error;
  134. case -2:
  135. KMessageBox::error(parentWidget,"Failed to connect to Qt Assistant.",
  136. "Socket Error");
  137. goto error;
  138. case -3:
  139. KMessageBox::error(parentWidget,"Connection to Qt Assistant timed out.",
  140. "Socket Error");
  141. goto error;
  142. default:
  143. KMessageBox::error(parentWidget,"Socket Error.");
  144. error:
  145. disconnect(procIO,SIGNAL(processExited(KProcess*)),
  146. this,SLOT(procIO_processExited()));
  147. disconnect(procIO,SIGNAL(readReady(KProcIO*)),
  148. this,SLOT(procIO_readReady()));
  149. procIO->deleteLater();
  150. procIO=static_cast<KProcIO *>(NULL);
  151. delete socket;
  152. socket=static_cast<KExtendedSocket *>(NULL);
  153. return;
  154. }
  155. continue;
  156. }
  157. }
  158. KMessageBox::error(parentWidget,line,"Qt Assistant Error");
  159. }
  160. }