1 // Copyright 2010 Ilkka Tengvall
3 // This file is part of Woller.
5 // Woller is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // Woller is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Woller. If not, see <http://www.gnu.org/licenses/>.
24 MainWindow::MainWindow()
27 this->setAttribute(Qt::WA_Maemo5StackedWindow);
29 woller = new Woller(this);
30 this->setCentralWidget(woller);
33 MainWindow::~MainWindow()
39 Woller::Woller(QWidget *parent)
42 QList<QString> targets;
43 status_orig = new QString(
44 tr("Choose the target or configure and fire it up!"));
45 status_timer = new QTimer(this);
46 hosts_list = new QList<host_s>;
47 settings = new QSettings("woller", "woller");
48 // build the main widget
49 this->setWindowIcon(QIcon::fromTheme("woller", QIcon(":/woller.png")));
50 status_lbl = new QLabel(*status_orig , this);
51 fire_btn = new QPushButton(tr("Wake UP"), this);
53 tr("Press the button to wake up selected target (or config)"));
54 fire_btn->setIcon(QIcon::fromTheme("woller", QIcon(":/woller.png")));
55 targets_cb = new QComboBox(this);
56 targets_cb->setToolTip(
57 tr("Choose host to wake up, or configure hosts option"));
59 vlayout = new QVBoxLayout();
60 hlayout = new QHBoxLayout();
61 hlayout->addWidget(targets_cb);
62 hlayout->addWidget(fire_btn);
63 vlayout->addWidget(status_lbl);
64 vlayout->addLayout(hlayout);
65 this->setLayout(vlayout);
66 this->setWindowTitle(tr("Woller-program"));
68 this->setAttribute(Qt::WA_Maemo5StackedWindow);
70 this->setWindowModality(Qt::ApplicationModal);
76 target = new wol_target;
78 connect(fire_btn, SIGNAL(clicked()), this, SLOT(send_pkt()));
79 connect(targets_cb, SIGNAL(activated(int)), this, SLOT(targets_act(int)));
84 int i = targets_cb->currentIndex();
85 qDebug() << "~Woller" << endl;
86 qDebug() << "~Woller last" << i << endl;
87 settings->setValue("last selected", i);
88 settings->setValue("position", pos());
101 void Woller::send_pkt()
103 int t = targets_cb->currentIndex();
111 if (!hosts_list->isEmpty() && t-1 <= hosts_list->count())
113 QString status = "Sent wakeup packet to ";
114 status.append(hosts_list->at(t-1).hostname);
115 target->set_mac(hosts_list->at(t-1).mac);
116 target->set_ip(hosts_list->at(t-1).ip);
118 status_lbl->setText(status);
119 status_timer->singleShot(5000, this, SLOT(reset_status()));
124 void Woller::reset_status()
126 status_lbl->setText(*status_orig);
129 void Woller::targets_act(int i)
133 // build the config widget
134 qDebug() << "building the config" << endl;
135 config_win = new ConfigWidget(this, hosts_list);
136 connect(config_win, SIGNAL(hosts_changed()), this, SLOT(hosts_changed()));
141 qDebug() << "targets: " << targets_cb->currentText() << endl;
145 void Woller::add_new(host_s *host)
147 qDebug() << "add_new:" << host->hostname << host->ip << host->mac << endl;
150 void Woller::do_list()
152 qDebug() << "do_list" << endl;
155 targets_cb->addItem(tr("Configure Targets"));
156 for (int i = 0; i < hosts_list->size(); ++i) {
157 targets_cb->addItem(hosts_list->at(i).hostname);
161 void Woller::hosts_changed()
163 qDebug() << "hosts_changed" << endl;
168 void Woller::save_config()
170 qDebug() << "save config" << endl;
171 settings->beginWriteArray("targets");
172 for (int i = 0; i < hosts_list->count(); ++i) {
173 settings->setArrayIndex(i);
174 settings->setValue("hostname", hosts_list->at(i).hostname);
175 settings->setValue("ip", hosts_list->at(i).ip.toString().toAscii());
176 settings->setValue("mac", hosts_list->at(i).mac.toAscii());
178 settings->endArray();
181 void Woller::load_config()
184 qDebug() << "loading config" << endl;
185 int size = settings->beginReadArray("targets");
186 for (int i = 0; i < size; ++i) {
187 settings->setArrayIndex(i);
188 host.hostname = settings->value("hostname").toString();
189 host.ip.setAddress(settings->value("ip").toString());
190 host.mac = settings->value("mac").toString();
191 hosts_list->append(host);
193 settings->endArray();
195 move(settings->value("position", QPoint(200, 200)).toPoint());
199 targets_cb->setCurrentIndex(settings->value("last selected", 0).toInt());
203 ConfigWidget::ConfigWidget(QWidget *parent, QList<host_s> *hosts)
206 qDebug() << "ConfigWidget" << endl;
209 //add buttons and the list
210 this->setWindowTitle(tr("Woller Config"));
212 this->setAttribute(Qt::WA_Maemo5StackedWindow);
214 this->setWindowModality(Qt::ApplicationModal);
216 this->setWindowFlags(this->windowFlags() | Qt::Window);
217 add_host = new QPushButton(tr("&Add Host"), this);
218 edit_host = new QPushButton(tr("&Edit Host"), this);
219 del_host = new QPushButton(tr("&Delete Host"), this);
220 save_btn = new QPushButton(tr("&Save"), this);
221 close_btn = new QPushButton(tr("&Close"), this);
222 list = new QListWidget(this);
223 button_layout = new QVBoxLayout();
224 layout = new QHBoxLayout();
225 button_layout->addWidget(add_host);
226 button_layout->addWidget(edit_host);
227 button_layout->addWidget(del_host);
228 button_layout->addWidget(save_btn);
229 button_layout->addWidget(close_btn);
230 layout->addWidget(list);
231 layout->addLayout(button_layout);
232 this->setLayout(layout);
233 close_btn->setDefault(true);
234 edit_host->setDisabled(true);
235 del_host->setDisabled(true);
236 save_btn->setDisabled(true);
238 connect(add_host, SIGNAL(clicked()), this, SLOT(add_sig()));
239 connect(edit_host, SIGNAL(clicked()), this, SLOT(edit_sig()));
240 connect(del_host, SIGNAL(clicked()), this, SLOT(del_sig()));
241 connect(save_btn, SIGNAL(clicked()), this, SLOT(save_sig()));
242 connect(close_btn, SIGNAL(clicked()), this, SLOT(close_sig()));
243 connect(list, SIGNAL(itemClicked(QListWidgetItem *)), this,
245 connect(list, SIGNAL(itemActivated(QListWidgetItem *)), this,
248 for (int i = 0; i < hosts_list->size(); ++i) {
249 list->addItem(hosts_list->at(i).hostname);
253 ConfigWidget::~ConfigWidget()
261 delete button_layout;
266 void ConfigWidget::add_sig()
268 qDebug() << "conf add" << endl;
269 host_tmp.hostname.clear();
270 host_tmp.mac.clear();
272 host_widget = new HostWidget(this, &host_tmp);
274 connect(host_widget, SIGNAL(change_host()), this, SLOT(host_added()));
276 qDebug() << "conf add - exit" << endl;
280 void ConfigWidget::edit_sig()
282 qDebug() << "conf edit" << endl;
283 host_tmp.hostname = hosts_list->at(list->currentIndex().row()).hostname;
284 host_tmp.mac = hosts_list->at(list->currentIndex().row()).mac;
285 host_tmp.ip = hosts_list->at(list->currentIndex().row()).ip;
286 host_widget = new HostWidget(this, &host_tmp);
287 connect(host_widget, SIGNAL(change_host()), this, SLOT(host_edited()));
289 //hostWidget->hostname->setPlaceholderText("my_host_name");
290 //hostWidget->hostname->setText("edit1");
291 //hostWidget->mac->setPlaceholderText("001133aabbcc");
292 //hostWidget->mac->setText("001133aabbcc");
293 //hostWidget->ip->setPlaceholderText("10.10.11.255");
297 void ConfigWidget::del_sig()
300 int ret, i = list->currentIndex().row();
301 qDebug() << "conf del: " << i << endl;
303 msg_box.setText("Host is to be deleted.");
304 msg_box.setInformativeText("Do you want to save your changes?");
305 msg_box.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
306 msg_box.setDefaultButton(QMessageBox::Save);
307 ret = msg_box.exec();
309 if ( ret == QMessageBox::Save ) {
310 hosts_list->removeAt(i);
312 emit hosts_changed();
316 void ConfigWidget::save_sig()
318 qDebug() << "conf save" << endl;
319 emit hosts_changed();
320 save_btn->setDisabled(true);
323 void ConfigWidget::close_sig()
325 qDebug() << "conf close" << endl;
329 void ConfigWidget::select_sig()
331 qDebug() << "conf sel: " << endl;
332 edit_host->setDisabled(false);
333 del_host->setDisabled(false);
336 void ConfigWidget::host_added()
338 qDebug() << "host changed" << endl;
339 list->addItem(host_tmp.hostname);
340 qDebug() << "hostsList size:" << hosts_list->size()
341 << "count:" << hosts_list->size() << endl;
342 hosts_list->append(host_tmp);
343 qDebug() << "hostsList size:" << hosts_list->size()
344 << "count:" << hosts_list->size() << endl;
345 save_btn->setDisabled(false);
346 save_btn->setDefault(true);
349 void ConfigWidget::host_edited()
351 int i = list->currentIndex().row();
352 qDebug() << "host edited: " << i << endl;
354 hosts_list->replace(i, host_tmp);
356 list->insertItem(i, hosts_list->at(i).hostname);
357 save_btn->setDisabled(false);
358 save_btn->setDefault(true);
361 HostWidget::HostWidget(QWidget *parent, host_s *host)
364 //TODO: add setValidator and use QRegExpValidator
366 qDebug() << "host widget" << endl;
368 this->setWindowTitle(tr("WOL target details"));
370 this->setAttribute(Qt::WA_Maemo5StackedWindow);
372 this->setWindowModality(Qt::ApplicationModal);
374 this->setWindowFlags(this->windowFlags() | Qt::Window);
375 vlayout = new QVBoxLayout(this);
377 host_row = new QHBoxLayout;
378 host_lbl = new QLabel(tr("Hostname:"), this);
379 hostname = new QLineEdit(host->hostname, this);
380 hostname->setToolTip(tr("Give target computer's hostname"));
381 host_row->addWidget(host_lbl);
382 host_row->addWidget(hostname);
383 vlayout->addLayout(host_row);
385 mac_row = new QHBoxLayout;
386 mac_lbl = new QLabel(tr("Mac:"), this);
387 mac = new QLineEdit(host->mac, this);
389 tr("HW address of target, e.g. 00:01:02:AA:BB:CC. "
390 "Hint, in Linux/Unix: \"ifconfig\","
391 "in Windows \"ipconfig /all\""));
392 mac->setInputMask("HH:HH:HH:HH:HH:HH;_");
393 mac_row->addWidget(mac_lbl);
394 mac_row->addWidget(mac);
395 vlayout->addLayout(mac_row);
397 ip_row = new QHBoxLayout;
398 ip_lbl = new QLabel(tr("Bcast ip:"), this);
399 ip = new QLineEdit(host->ip.toString(), this);
401 tr("Use ip broadcast address if you want to wake up target outside"
402 "of local network, or if you have several network interfaces."
403 "E.g. 192.168.1.255. You may leave this empty if unsure."));
404 ip->setMaxLength(MAX_IP_LEN);
405 ip_row->addWidget(ip_lbl);
406 ip_row->addWidget(ip);
407 vlayout->addLayout(ip_row);
409 button_row = new QHBoxLayout;
410 cancel = new QPushButton(tr("&Cancel"), this);
411 button_row->addWidget(cancel);
412 ok = new QPushButton(tr("&Ok"), this);
413 ok->setDefault(true);
414 button_row->addWidget(ok);
415 vlayout->addLayout(button_row);
417 this->setLayout(vlayout);
419 ok->setDefault(true);
421 connect(ok, SIGNAL(clicked()), this, SLOT(ok_sig()));
422 connect(cancel, SIGNAL(clicked()), this, SLOT(cancel_sig()));
426 void HostWidget::cancel_sig()
428 qDebug() << "host cancel" << endl;
432 void HostWidget::ok_sig()
434 qDebug() << "host ok" << this->hostname->text() << this->mac->text()
435 << this->ip->text() << endl;
437 new_host->hostname = this->hostname->text();
438 if (new_host->hostname.isEmpty())
441 msgBox.setText("You must set hostname!");
446 new_host->mac = this->mac->text();
447 if (new_host->mac.length() != MAX_MAC_STR_LEN)
450 msgBox.setText("You must set mac to full 12 digits!\n" \
451 "E.g. 00:11:22:33:44:55:66");
455 new_host->ip = this->ip->text();
458 qDebug() << "host ok" << new_host->hostname << new_host->mac
459 << new_host->ip << endl;
464 HostWidget::~HostWidget()
466 qDebug() << "host ~widget" << endl;
483 int wol_target::get_mac( QString *gmac)
491 int wol_target::set_mac( const QString smac )
493 if (smac.size() != MAX_MAC_LEN) {
494 qDebug() << "set mac mac size:" << smac.size() << smac << endl;
498 qDebug() << "set mac mac:" << mac;
502 int wol_target::get_ip( QHostAddress *gip)
510 int wol_target::set_ip( const QHostAddress sip )
519 wol_target::wol_target()
522 ip = new QHostAddress;
523 magic_pkt = new QByteArray;
526 wol_target::~wol_target()
533 int wol_target::create_magic_pkt(const QString *mac)
535 const char magic_header[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
536 qDebug() << "create magic pkt" << endl;
537 if (mac->size() != MAX_MAC_LEN)
539 qDebug() << "create magic pkt size:" << mac->size() << endl;
542 *magic_pkt = QByteArray::fromRawData(magic_header, sizeof(magic_header));
543 for (int i=0; i < WOL_MAGIC_MAC_CNT; i++)
544 magic_pkt->append(QByteArray::fromHex(mac->toAscii()));
548 int wol_target::wake_me()
550 QUdpSocket udpSocket;
552 if (mac->isEmpty()) {
553 qDebug() << "wakeme: no mac set" << endl;
556 create_magic_pkt(mac);
557 qDebug() << "magic:" << endl;
558 qDebug() << magic_pkt->toHex() << endl ;
561 qDebug() << "sending broadcast to mac" << *mac << endl;
562 udpSocket.writeDatagram(magic_pkt->data(), magic_pkt->size(),
563 QHostAddress::Broadcast,
567 qDebug() << "sending with ip" << *ip << endl;
568 udpSocket.writeDatagram(magic_pkt->data(), magic_pkt->size(),