All Classes Namespaces Files Functions Variables Enumerations Enumerator
programs/UrgInformation/UrgInformationWidget.cpp
Go to the documentation of this file.
00001 
00010 #include "UrgInformationWidget.h"
00011 #include "SerialConnectionWidget.h"
00012 #include "Connection.h"
00013 #include "ConnectionUtils.h"
00014 #include "UrgUsbCom.h"
00015 #include "UrgDevice.h"
00016 #include "FindComPorts.h"
00017 #include "codedString.h"
00018 #include <QMessageBox>
00019 #include <QShortcut>
00020 #include <QFileDialog>
00021 #include <QTextStream>
00022 #include <string>
00023 
00024 using namespace qrk;
00025 using namespace std;
00026 
00027 
00028 namespace
00029 {
00030   const char* Version = "1.0.2";
00031 }
00032 
00033 
00034 struct UrgInformationWidget::pImpl
00035 {
00036   UrgInformationWidget* widget_;
00037   SerialConnectionWidget connection_widget_;
00038   QString message_;
00039   vector<QLabel*> result_labels_;
00040 
00041   UrgUsbCom urg_usb_;
00042   FindComPorts urg_finder_;
00043   UrgDevice urg_;
00044 
00045 
00046   pImpl(UrgInformationWidget* widget)
00047     : widget_(widget)
00048   {
00049     urg_finder_.addBaseName("/dev/ttyACM");
00050     urg_finder_.addBaseName("/dev/tty.usbmodem");
00051     urg_finder_.addDriverName("URG Series USB Device Driver");
00052     urg_finder_.addDriverName("URG-X002 USB Device Driver");
00053   }
00054 
00055 
00056   void initializeForm(void)
00057   {
00058     // タイトルにバージョン情報を付加
00059     const QString title =
00060       widget_->windowTitle() + " " + Version;
00061     widget_->setWindowTitle(title);
00062 
00063     // ConnectionWidget の配置
00064     widget_->connection_layout_->addWidget(&connection_widget_);
00065     widget_->connection_dummy_->hide();
00066 
00067     widget_->command_tab_->setCurrentIndex(0);
00068 
00069     message_ = tr("Select device, and press 'Connect'.");
00070     setEnabled(false);
00071 
00072     // 情報の出力先ポインタを確保
00073     result_labels_.push_back(widget_->vv_result_);
00074     result_labels_.push_back(widget_->pp_result_);
00075     result_labels_.push_back(widget_->ii_result_);
00076 
00077     // イベントの接続
00078     connect(&connection_widget_, SIGNAL(rescanRequest()),
00079             widget_, SLOT(rescanPressed()));
00080     connect(&connection_widget_,
00081             SIGNAL(connectRequest(bool, const std::string&)),
00082             widget_, SLOT(connectPressed(bool, const std::string&)));
00083     connect(widget_->save_button_, SIGNAL(clicked()),
00084             widget_, SLOT(saveLog()));
00085   }
00086 
00087 
00088   void setEnabled(bool enable)
00089   {
00090     widget_->message_label_->setText(message_);
00091     widget_->command_tab_->setEnabled(enable);
00092 
00093     if (! enable) {
00094       widget_->command_tab_->setCurrentIndex(0);
00095       for (vector<QLabel*>::iterator it = result_labels_.begin();
00096            it != result_labels_.end(); ++it) {
00097         (*it)->clear();
00098       }
00099     }
00100   }
00101 
00102 
00103   void updateInformatino(void)
00104   {
00105     Connection* con = urg_.connection();
00106 
00107     enum {
00108       BufferSize = 64,
00109       Timeout = 1000,
00110     };
00111     char buffer[BufferSize];
00112 
00113     // VV, PP, II の情報を取得して表示
00114     const char* commands[] = { "VV\n", "PP\n", "II\n" };
00115     size_t n = sizeof(commands) / sizeof(commands[0]);
00116     for (size_t i = 0; i < n; ++i) {
00117       con->send(commands[i], 3);
00118 
00119       QString lines;
00120       int n = 0;
00121       while (1) {
00122         n = readline(con, buffer, BufferSize, Timeout);
00123         if (n <= 0) {
00124           break;
00125         }
00126         buffer[n] = '\0';
00127         lines += QString(buffer) + "\n";
00128       }
00129       lines.remove(lines.size() - 1, 1);
00130 
00131       // 取得した情報を表示
00132       result_labels_[i]->setText(lines);
00133     }
00134     setEnabled(true);
00135   }
00136 
00137 
00138   void clearMessages(void)
00139   {
00140     widget_->vv_result_->clear();
00141     widget_->pp_result_->clear();
00142     widget_->ii_result_->clear();
00143   }
00144 };
00145 
00146 
00147 UrgInformationWidget::UrgInformationWidget(QWidget* parent)
00148   : QWidget(parent), pimpl(new pImpl(this))
00149 {
00150   setupUi(this);
00151 
00152   // フォームを初期化し、最初の表示を行う
00153   pimpl->initializeForm();
00154   rescanPressed();
00155 
00156   // Ctrl-q, Alt-F4 で終了させる
00157   (void) new QShortcut(Qt::CTRL + Qt::Key_Q, this, SLOT(close()));
00158   (void) new QShortcut(Qt::ALT + Qt::Key_F4, this, SLOT(close()));
00159 }
00160 
00161 
00162 UrgInformationWidget::~UrgInformationWidget(void)
00163 {
00164 }
00165 
00166 
00167 void UrgInformationWidget::rescanPressed(void)
00168 {
00169   vector<string> devices;
00170   pimpl->urg_finder_.find(devices);
00171   for (vector<string>::iterator it = devices.begin();
00172        it != devices.end(); ++it) {
00173     if (pimpl->urg_usb_.isUsbCom(it->c_str())) {
00174       *it = *it + " [URG]";
00175     }
00176   }
00177   pimpl->connection_widget_.setDevices(devices);
00178   if (! devices.empty()) {
00179     pimpl->connection_widget_.setFocus();
00180   }
00181 }
00182 
00183 
00184 void UrgInformationWidget::connectPressed(bool connection, const string& device)
00185 {
00186   // !!! 接続処理をスレッドで行うように調整する
00187   if (! connection) {
00188     return;
00189   }
00190   pimpl->clearMessages();
00191   save_button_->setEnabled(false);
00192 
00193   if (! pimpl->urg_.connect(device.c_str())) {
00194     QString error_message = localedToUnicode(pimpl->urg_.what());
00195     QMessageBox::warning(this, tr("Connection error"), error_message);
00196     pimpl->connection_widget_.setConnected(false);
00197     return;
00198   }
00199 
00200   save_button_->setEnabled(true);
00201 
00202   // 情報を更新後、切断する
00203   pimpl->updateInformatino();
00204   pimpl->connection_widget_.setConnected(false);
00205   pimpl->urg_.disconnect();
00206 }
00207 
00208 
00209 void UrgInformationWidget::saveLog(void)
00210 {
00211   QString default_file_name = "UrgInformation_log.txt";
00212   QString file_name =
00213     QFileDialog::getSaveFileName(this, tr("Save information log."),
00214                                  default_file_name, tr("txt (*.txt)"));
00215   if (file_name.isEmpty()) {
00216     return;
00217   }
00218 
00219   // 保存
00220   QFile save_file(file_name);
00221   if (! save_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
00222     return;
00223   }
00224   QTextStream fout(&save_file);
00225   fout << vv_result_->text() << endl
00226        << endl
00227        << pp_result_->text() << endl
00228        << endl
00229        << ii_result_->text() << endl;
00230 }