Merge branch 'master' of ssh://woller-gui.git.sourceforge.net/gitroot/woller-gui...
[woller] / woller.cpp
diff --git a/woller.cpp b/woller.cpp
new file mode 100644 (file)
index 0000000..58d1e85
--- /dev/null
@@ -0,0 +1,542 @@
+// Copyright 2010 Ilkka Tengvall
+//
+// This file is part of Woller.
+//
+// Woller is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Woller is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Woller.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "woller.h"
+
+
+Woller::Woller(QWidget *parent)
+        : QWidget(parent)
+{
+    QList<QString> targets;
+    status_orig = new QString(
+            tr("Choose the target or configure and fire it up!"));
+    status_timer = new QTimer(this);
+    hosts_list = new QList<host_s>;
+    settings = new QSettings("woller", "woller");
+    // build the main widget
+    this->setWindowIcon(QIcon::fromTheme("woller", QIcon(":/woller.png")));
+    status_lbl = new QLabel(*status_orig , this);
+    fire_btn = new QPushButton(tr("Wake UP"), this);
+    fire_btn->setToolTip(
+            tr("Press the button to wake up selected target (or config)"));
+    fire_btn->setIcon(QIcon::fromTheme("woller", QIcon(":/woller.png")));
+    targets_cb = new QComboBox(this);
+    targets_cb->setToolTip(
+            tr("Choose host to wake up, or configure hosts option"));
+
+    vlayout = new QVBoxLayout();
+    hlayout = new QHBoxLayout();
+    hlayout->addWidget(targets_cb);
+    hlayout->addWidget(fire_btn);
+    vlayout->addWidget(status_lbl);
+    vlayout->addLayout(hlayout);
+    this->setLayout(vlayout);
+    this->setWindowTitle(tr("Woller-program"));
+
+    //populate CB
+    load_config();
+
+    target = new wol_target;
+
+    connect(fire_btn, SIGNAL(clicked()), this, SLOT(send_pkt()));
+    connect(targets_cb, SIGNAL(activated(int)), this, SLOT(targets_act(int)));
+}
+
+Woller::~Woller()
+{
+    int i = targets_cb->currentIndex();
+    qDebug() << "~Woller" << endl;
+    qDebug() << "~Woller last" << i << endl;
+    settings->setValue("last selected", i);
+    settings->setValue("position", pos());
+    delete settings;
+    delete hosts_list;
+    delete status_lbl;
+    delete fire_btn;
+    delete targets_cb;
+    //delete vlayout;
+    //delete hlayout;
+    delete target;
+    delete status_orig;
+    delete status_timer;
+}
+
+void Woller::send_pkt()
+{
+    int t = targets_cb->currentIndex();
+
+    if (t == 0)
+    {
+        targets_act(0);
+    }
+    else
+    {
+        if (!hosts_list->isEmpty() && t-1 <= hosts_list->count())
+        {
+            QString status = "Sent wakeup packet to ";
+            status.append(hosts_list->at(t-1).hostname);
+            target->set_mac(hosts_list->at(t-1).mac);
+            target->set_ip(hosts_list->at(t-1).ip);
+            target->wake_me();
+            status_lbl->setText(status);
+            status_timer->singleShot(5000, this, SLOT(reset_status()));
+        }
+    }
+}
+
+void Woller::reset_status()
+{
+    status_lbl->setText(*status_orig);
+}
+
+void Woller::targets_act(int i)
+{
+    if (i == 0)
+    {
+        // build the config widget
+        qDebug() << "building the config" << endl;
+        config_win = new ConfigWidget(0, hosts_list);
+        config_win->setWindowModality(Qt::ApplicationModal);
+        connect(config_win, SIGNAL(hosts_changed()), this, SLOT(hosts_changed()));
+        config_win->show();
+    }
+    else
+    {
+        qDebug() << "targets: " << targets_cb->currentText() << endl;
+    }
+}
+
+void Woller::add_new(host_s *host)
+{
+    qDebug() << "add_new:" << host->hostname << host->ip << host->mac << endl;
+}
+
+void Woller::do_list()
+{
+    qDebug() << "do_list" << endl;
+    //populate CB
+    targets_cb->clear();
+    targets_cb->addItem(tr("Configure Targets"));
+    for (int i = 0; i < hosts_list->size(); ++i) {
+        targets_cb->addItem(hosts_list->at(i).hostname);
+     }
+}
+
+void Woller::hosts_changed()
+{
+    qDebug() << "hosts_changed" << endl;
+    do_list();
+    save_config();
+}
+
+void Woller::save_config()
+{
+    qDebug() << "save config" << endl;
+    settings->beginWriteArray("targets");
+    for (int i = 0; i < hosts_list->count(); ++i) {
+        settings->setArrayIndex(i);
+        settings->setValue("hostname", hosts_list->at(i).hostname);
+        settings->setValue("ip", hosts_list->at(i).ip.toString().toAscii());
+        settings->setValue("mac", hosts_list->at(i).mac.toAscii());
+     }
+    settings->endArray();
+}
+
+void Woller::load_config()
+{
+    host_s host;
+    qDebug() << "loading config" << endl;
+    int size = settings->beginReadArray("targets");
+    for (int i = 0; i < size; ++i) {
+        settings->setArrayIndex(i);
+        host.hostname = settings->value("hostname").toString();
+        host.ip.setAddress(settings->value("ip").toString());
+        host.mac = settings->value("mac").toString();
+        hosts_list->append(host);
+    }
+    settings->endArray();
+
+    move(settings->value("position", QPoint(200, 200)).toPoint());
+
+    do_list();
+
+    targets_cb->setCurrentIndex(settings->value("last selected", 0).toInt());
+}
+
+
+ConfigWidget::ConfigWidget(QWidget *parent, QList<host_s> *hosts)
+        : QWidget(parent)
+{
+    qDebug() << "ConfigWidget" << endl;
+    hosts_list = hosts;
+
+    //add buttons and the list
+    this->setWindowTitle(tr("Woller Config"));
+    add_host = new QPushButton(tr("&Add Host"), this);
+    edit_host = new QPushButton(tr("&Edit Host"), this);
+    del_host = new QPushButton(tr("&Delete Host"), this);
+    save_btn = new QPushButton(tr("&Save"), this);
+    close_btn = new QPushButton(tr("&Close"), this);
+    list = new QListWidget(this);
+    button_layout = new QVBoxLayout();
+    layout = new QHBoxLayout();
+    button_layout->addWidget(add_host);
+    button_layout->addWidget(edit_host);
+    button_layout->addWidget(del_host);
+    button_layout->addWidget(save_btn);
+    button_layout->addWidget(close_btn);
+    layout->addWidget(list);
+    layout->addLayout(button_layout);
+    this->setLayout(layout);
+    close_btn->setDefault(true);
+    edit_host->setDisabled(true);
+    del_host->setDisabled(true);
+    save_btn->setDisabled(true);
+
+    connect(add_host, SIGNAL(clicked()), this, SLOT(add_sig()));
+    connect(edit_host, SIGNAL(clicked()), this, SLOT(edit_sig()));
+    connect(del_host, SIGNAL(clicked()), this, SLOT(del_sig()));
+    connect(save_btn, SIGNAL(clicked()), this, SLOT(save_sig()));
+    connect(close_btn, SIGNAL(clicked()), this, SLOT(close_sig()));
+    connect(list, SIGNAL(itemClicked(QListWidgetItem *)), this,
+            SLOT(select_sig()));
+    connect(list, SIGNAL(itemActivated(QListWidgetItem *)), this,
+            SLOT(edit_sig()));
+
+    for (int i = 0; i < hosts_list->size(); ++i) {
+        list->addItem(hosts_list->at(i).hostname);
+     }
+}
+
+ConfigWidget::~ConfigWidget()
+{
+    delete add_host;
+    delete edit_host;
+    delete del_host;
+    delete save_btn;
+    delete close_btn;
+    delete list;
+    delete button_layout;
+    delete layout;
+}
+
+
+void ConfigWidget::add_sig()
+{
+    qDebug() << "conf add" << endl;
+    host_tmp.hostname.clear();
+    host_tmp.mac.clear();
+    host_tmp.ip.clear();
+    host_widget = new HostWidget(0, &host_tmp);
+
+    host_widget->setWindowModality(Qt::ApplicationModal);
+    connect(host_widget, SIGNAL(change_host()), this, SLOT(host_added()));
+    host_widget->show();
+    qDebug() << "conf add - exit" << endl;
+
+}
+
+void ConfigWidget::edit_sig()
+{
+    qDebug() << "conf edit" << endl;
+    host_tmp.hostname = hosts_list->at(list->currentIndex().row()).hostname;
+    host_tmp.mac = hosts_list->at(list->currentIndex().row()).mac;
+    host_tmp.ip = hosts_list->at(list->currentIndex().row()).ip;
+    host_widget = new HostWidget(0, &host_tmp);
+    connect(host_widget, SIGNAL(change_host()), this, SLOT(host_edited()));
+
+    host_widget->setWindowModality(Qt::ApplicationModal);
+    //hostWidget->hostname->setPlaceholderText("my_host_name");
+    //hostWidget->hostname->setText("edit1");
+    //hostWidget->mac->setPlaceholderText("001133aabbcc");
+    //hostWidget->mac->setText("001133aabbcc");
+    //hostWidget->ip->setPlaceholderText("10.10.11.255");
+    host_widget->show();
+}
+
+void ConfigWidget::del_sig()
+{
+    QMessageBox msg_box;
+    int ret, i = list->currentIndex().row();
+    qDebug() << "conf del: " << i << endl;
+
+    msg_box.setText("Host is to be deleted.");
+    msg_box.setInformativeText("Do you want to save your changes?");
+    msg_box.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
+    msg_box.setDefaultButton(QMessageBox::Save);
+    ret = msg_box.exec();
+
+    if ( ret ==  QMessageBox::Save ) {
+        hosts_list->removeAt(i);
+        list->takeItem(i);
+        emit hosts_changed();
+    }
+}
+
+void ConfigWidget::save_sig()
+{
+    qDebug() << "conf save" << endl;
+    emit hosts_changed();
+    save_btn->setDisabled(true);
+}
+
+void ConfigWidget::close_sig()
+{
+    qDebug() << "conf close" << endl;
+    this->close();
+}
+
+void ConfigWidget::select_sig()
+{
+    qDebug() << "conf sel: " << endl;
+    edit_host->setDisabled(false);
+    del_host->setDisabled(false);
+}
+
+void ConfigWidget::host_added()
+{
+    qDebug() << "host changed" << endl;
+    list->addItem(host_tmp.hostname);
+    qDebug() << "hostsList size:" << hosts_list->size()
+        << "count:" << hosts_list->size() << endl;
+    hosts_list->append(host_tmp);
+    qDebug() << "hostsList size:" << hosts_list->size()
+        << "count:" << hosts_list->size() << endl;
+    save_btn->setDisabled(false);
+    save_btn->setDefault(true);
+}
+
+void ConfigWidget::host_edited()
+{
+    int i = list->currentIndex().row();
+    qDebug() << "host edited: " << i << endl;
+
+    hosts_list->replace(i, host_tmp);
+    list->takeItem(i);
+    list->insertItem(i, hosts_list->at(i).hostname);
+    save_btn->setDisabled(false);
+    save_btn->setDefault(true);
+}
+
+HostWidget::HostWidget(QWidget *parent, host_s *host)
+        : QWidget(parent)
+{
+    //TODO: add setValidator and use QRegExpValidator
+
+    qDebug() << "host widget" << endl;
+    new_host = host;
+    this->setWindowTitle("Add new WOL target host");
+    vlayout = new QVBoxLayout(this);
+
+    host_row = new QHBoxLayout;
+    host_lbl = new QLabel(tr("Hostname:"), this);
+    hostname = new QLineEdit(host->hostname, this);
+    hostname->setToolTip(tr("Give target computer's hostname"));
+    host_row->addWidget(host_lbl);
+    host_row->addWidget(hostname);
+    vlayout->addLayout(host_row);
+
+    mac_row = new QHBoxLayout;
+    mac_lbl = new QLabel(tr("Mac:"), this);
+    mac = new QLineEdit(host->mac, this);
+    mac->setToolTip(
+            tr("HW address of target, e.g. 00:01:02:AA:BB:CC. "
+               "Hint, in Linux/Unix: \"ifconfig\","
+               "in Windows \"ipconfig /all\""));
+    mac->setInputMask("HH:HH:HH:HH:HH:HH;0");
+    mac_row->addWidget(mac_lbl);
+    mac_row->addWidget(mac);
+    vlayout->addLayout(mac_row);
+
+    ip_row = new QHBoxLayout;
+    ip_lbl = new QLabel(tr("Bcast ip:"), this);
+    ip = new QLineEdit(host->ip.toString(), this);
+    ip->setToolTip(
+            tr("Use ip broadcast address if you want to wake up target outside"
+               "of local network, or if you have several network interfaces."
+               "E.g. 192.168.1.255. You may leave this empty if unsure."));
+    ip->setMaxLength(MAX_IP_LEN);
+    ip_row->addWidget(ip_lbl);
+    ip_row->addWidget(ip);
+    vlayout->addLayout(ip_row);
+
+    button_row = new QHBoxLayout;
+    cancel = new QPushButton(tr("&Cancel"), this);
+    button_row->addWidget(cancel);
+    ok = new QPushButton(tr("&Ok"), this);
+    ok->setDefault(true);
+    button_row->addWidget(ok);
+    vlayout->addLayout(button_row);
+
+    this->setLayout(vlayout);
+
+    ok->setDefault(true);
+
+    connect(ok, SIGNAL(clicked()), this, SLOT(ok_sig()));
+    connect(cancel, SIGNAL(clicked()), this, SLOT(cancel_sig()));
+
+}
+
+void HostWidget::cancel_sig()
+{
+    qDebug() << "host cancel" << endl;
+    this->close();
+}
+
+void HostWidget::ok_sig()
+{
+    qDebug() << "host ok" << this->hostname->text() << this->mac->text()
+            << this->ip->text() << endl;
+
+    new_host->hostname = this->hostname->text();
+    if (new_host->hostname.isEmpty())
+    {
+        QMessageBox msgBox;
+        msgBox.setText("You must set hostname!");
+        msgBox.exec();
+        return;
+    }
+    new_host->mac= this->mac->text();
+    if (new_host->mac.isEmpty())
+    {
+        QMessageBox msgBox;
+        msgBox.setText("You must set mac!");
+        msgBox.exec();
+        return;
+    }
+    new_host->ip = this->ip->text();
+    emit change_host();
+
+    qDebug() << "host ok" << new_host->hostname << new_host->mac
+            << new_host->ip << endl;
+
+    this->close();
+}
+
+HostWidget::~HostWidget()
+{
+    qDebug() << "host ~widget" << endl;
+    delete vlayout;
+    delete host_row;
+    delete host_lbl;
+    delete hostname;
+    delete mac_row;
+    delete mac_lbl;
+    delete mac;
+    delete ip_row;
+    delete ip_lbl;
+    delete ip;
+    delete button_row;
+    delete cancel;
+    delete ok;
+    //delete new_host;
+}
+
+
+int wol_target::get_mac( QString *gmac)
+{
+    if (!gmac)
+        return -1;
+    *gmac = *mac;
+    return 0;
+}
+
+int wol_target::set_mac( const QString smac )
+{
+    if (smac.size() != MAX_MAC_LEN) {
+        qDebug() << "set mac mac size:" << smac.size() << smac << endl;
+        //return -1;
+    }
+    *mac = smac;
+    qDebug() << "set mac mac:" << mac;
+    return 0;
+}
+
+int wol_target::get_ip( QHostAddress *gip)
+{
+    if (!gip)
+        return -1;
+    *gip = *ip;
+    return 0;
+}
+
+int wol_target::set_ip( const QHostAddress sip )
+{
+    if (sip.isNull())
+        return -1;
+    *ip = sip;
+    return 0;
+}
+
+
+wol_target::wol_target()
+{
+    mac = new QString;
+    ip = new QHostAddress;
+    magic_pkt = new QByteArray;
+}
+
+wol_target::~wol_target()
+{
+    delete mac;
+    delete ip;
+    delete magic_pkt;
+}
+
+int wol_target::create_magic_pkt(const QString *mac)
+{
+    const char magic_header[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+    qDebug() << "create magic pkt" << endl;
+    if (mac->size() != MAX_MAC_LEN)
+    {
+        qDebug() << "create magic pkt size:" << mac->size() << endl;
+        //return -1;
+    }
+    *magic_pkt = QByteArray::fromRawData(magic_header, sizeof(magic_header));
+    for (int i=0; i < WOL_MAGIC_MAC_CNT; i++)
+        magic_pkt->append(QByteArray::fromHex(mac->toAscii()));
+    return 0;
+}
+
+int wol_target::wake_me()
+{
+    QUdpSocket udpSocket;
+
+    if (mac->isEmpty()) {
+        qDebug() << "wakeme: no mac set" << endl;
+        return -1;
+    }
+    create_magic_pkt(mac);
+    qDebug() << "magic:" << endl;
+    qDebug() << magic_pkt->toHex() << endl ;
+
+    if (ip->isNull()) {
+        qDebug() << "sending broadcast to mac" << *mac << endl;
+        udpSocket.writeDatagram(magic_pkt->data(), magic_pkt->size(),
+                                QHostAddress::Broadcast,
+                                WOL_MAGIC_UDP_PORT);
+    }
+    else {
+        qDebug() << "sending with ip" << *ip << endl;
+        udpSocket.writeDatagram(magic_pkt->data(), magic_pkt->size(),
+                                *ip,
+                                WOL_MAGIC_UDP_PORT);
+    }
+    return 0;
+}
+