Skip to content

Commit

Permalink
Shell: Added status widget
Browse files Browse the repository at this point in the history
The status widget shows the status of the shell connection and
a summary of status information from the server, when connected.
  • Loading branch information
skyjake committed Jan 25, 2013
1 parent 644c198 commit de17552
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 8 deletions.
6 changes: 4 additions & 2 deletions doomsday/tools/shell/shell-text/shell-text.pro
Expand Up @@ -29,15 +29,17 @@ HEADERS += \
src/cursestextcanvas.h \
src/logwidget.h \
src/main.h \
src/shellapp.h
src/shellapp.h \
src/statuswidget.h

SOURCES += \
src/commandlinewidget.cpp \
src/cursesapp.cpp \
src/cursestextcanvas.cpp \
src/logwidget.cpp \
src/main.cpp \
src/shellapp.cpp
src/shellapp.cpp \
src/statuswidget.cpp

# Installation --------------------------------------------------------------

Expand Down
19 changes: 19 additions & 0 deletions doomsday/tools/shell/shell-text/src/cursesapp.cpp
Expand Up @@ -25,9 +25,11 @@
#include <curses.h>
#include <stdio.h>
#include <de/Clock>
#include <de/Error>
#include <de/Animation>
#include <de/Rule>
#include <de/Vector>
#include <de/LogBuffer>
#include <de/shell/TextRootWidget>
#include <de/shell/TextWidget>
#include <de/shell/KeyEvent>
Expand Down Expand Up @@ -65,6 +67,7 @@ static de::Vector2i actualTerminalSize()
struct CursesApp::Instance
{
CursesApp &self;
de::LogBuffer logBuffer;
de::Clock clock;

// Curses state:
Expand All @@ -77,6 +80,9 @@ struct CursesApp::Instance

Instance(CursesApp &a) : self(a), unicodeContinuation(0), rootWidget(0)
{
logBuffer.enableStandardOutput(false);

de::LogBuffer::setAppBuffer(logBuffer);
de::Animation::setClock(&clock);
de::Clock::setAppClock(&clock);

Expand Down Expand Up @@ -311,6 +317,19 @@ CursesApp::~CursesApp()
delete d;
}

bool CursesApp::notify(QObject *receiver, QEvent *event)
{
try
{
return QCoreApplication::notify(receiver, event);
}
catch(de::Error const &er)
{
qDebug() << "Caught exception:" << er.asText().toAscii().constData();
}
return false;
}

TextRootWidget &CursesApp::rootWidget()
{
return *d->rootWidget;
Expand Down
2 changes: 2 additions & 0 deletions doomsday/tools/shell/shell-text/src/cursesapp.h
Expand Up @@ -30,6 +30,8 @@ class CursesApp : public QCoreApplication
CursesApp(int &argc, char **argv);
~CursesApp();

bool notify(QObject *receiver, QEvent *event);

de::shell::TextRootWidget &rootWidget();

protected slots:
Expand Down
3 changes: 2 additions & 1 deletion doomsday/tools/shell/shell-text/src/cursestextcanvas.cpp
Expand Up @@ -69,7 +69,8 @@ void CursesTextCanvas::show()
wattrset(d->window,
(ch.attribs.testFlag(Char::Bold)? A_BOLD : 0) |
(ch.attribs.testFlag(Char::Reverse)? A_REVERSE : 0) |
(ch.attribs.testFlag(Char::Underline)? A_UNDERLINE : 0));
(ch.attribs.testFlag(Char::Underline)? A_UNDERLINE : 0) |
(ch.attribs.testFlag(Char::Blink)? A_BLINK : 0));

// TODO: What about Unicode output? (libncursesw?)
waddch(d->window, ch.ch.toAscii()); // cursor advanced
Expand Down
34 changes: 29 additions & 5 deletions doomsday/tools/shell/shell-text/src/shellapp.cpp
Expand Up @@ -19,6 +19,9 @@
#include "shellapp.h"
#include "logwidget.h"
#include "commandlinewidget.h"
#include "statuswidget.h"
#include <de/shell/Link>
#include <QStringList>

using namespace de;

Expand All @@ -27,16 +30,25 @@ struct ShellApp::Instance
ShellApp &self;
LogWidget *log;
CommandLineWidget *cli;
StatusWidget *status;
shell::Link *link;

Instance(ShellApp &a) : self(a)
Instance(ShellApp &a) : self(a), link(0)
{
RootWidget &root = self.rootWidget();

status = new StatusWidget;
status->rule()
.setInput(RectangleRule::Height, refless(new ConstantRule(1)))
.setInput(RectangleRule::Bottom, root.viewBottom())
.setInput(RectangleRule::Width, root.viewWidth())
.setInput(RectangleRule::Left, root.viewLeft());

cli = new CommandLineWidget;
cli->rule()
.setInput(RectangleRule::Left, root.viewLeft())
.setInput(RectangleRule::Width, root.viewWidth())
.setInput(RectangleRule::Bottom, root.viewBottom());
.setInput(RectangleRule::Bottom, status->rule().top());

log = new LogWidget;
log->rule()
Expand All @@ -45,6 +57,8 @@ struct ShellApp::Instance
.setInput(RectangleRule::Top, root.viewTop())
.setInput(RectangleRule::Bottom, cli->rule().top());

// Ownership also given to the root widget:
root.add(status);
root.add(cli);
root.add(log);

Expand All @@ -54,12 +68,23 @@ struct ShellApp::Instance
}

~Instance()
{}
{
delete link;
}
};

ShellApp::ShellApp(int &argc, char **argv)
: CursesApp(argc, argv), d(new Instance(*this))
{}
{
QStringList args = arguments();

if(args.size() > 1)
{
// Open a connection.
d->link = new shell::Link(Address(args[1]));
d->status->setShellLink(d->link);
}
}

ShellApp::~ShellApp()
{
Expand All @@ -72,4 +97,3 @@ void ShellApp::sendCommandToServer(String command)

// todo
}

2 changes: 2 additions & 0 deletions doomsday/tools/shell/shell-text/src/shellapp.h
Expand Up @@ -23,6 +23,8 @@

class ShellApp : public CursesApp
{
Q_OBJECT

public:
ShellApp(int &argc, char **argv);

Expand Down
115 changes: 115 additions & 0 deletions doomsday/tools/shell/shell-text/src/statuswidget.cpp
@@ -0,0 +1,115 @@
/** @file statuswidget.cpp Widget for status information.
*
* @authors Copyright © 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program 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 2 of the License, or (at your
* option) any later version. This program 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 this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#include "statuswidget.h"
#include <QTimer>
#include <de/shell/TextRootWidget>

using namespace de;
using namespace de::shell;

struct StatusWidget::Instance
{
StatusWidget &self;
Link *link;
QTimer *updateTimer;

Instance(StatusWidget &i) : self(i), link(0)
{
updateTimer = new QTimer(&self);
}
};

StatusWidget::StatusWidget(String const &name)
: TextWidget(name), d(new Instance(*this))
{
connect(d->updateTimer, SIGNAL(timeout()), this, SLOT(redraw()));
}

StatusWidget::~StatusWidget()
{
delete d;
}

void StatusWidget::setShellLink(Link *link)
{
d->link = link;

if(link)
{
// Observe changes in link status.
connect(link, SIGNAL(connected()), this, SLOT(linkConnected()));
connect(link, SIGNAL(disconnected()), this, SLOT(linkDisconnected()));
}

root().requestDraw();
}

void StatusWidget::draw()
{
if(!targetCanvas()) return;

Rectanglei pos = rule().recti();
TextCanvas buf(pos.size());

if(!d->link || d->link->status() == Link::Disconnected)
{
String msg = "Not connected to a server";
buf.drawText(Vector2i(buf.size().x/2 - msg.size()/2), msg, TextCanvas::Char::Bold);
}
else if(d->link->status() == Link::Connecting)
{
String msg = "Connecting to " + d->link->address().asText();
buf.drawText(Vector2i(buf.size().x/2 - msg.size()/2), msg);
}
else if(d->link->status() == Link::Connected)
{
TimeDelta elapsed = d->link->connectedAt().since();
String time = String("| %1:%2:%3")
.arg(int(elapsed.asHours()))
.arg(int(elapsed.asMinutes()) % 60)
.arg(int(elapsed) % 60);
String host = "| " + d->link->address().asText();

int x = buf.size().x - time.size() - 1;
buf.drawText(x, time);

x -= host.size() + 1;
buf.drawText(x, host);
}

buf.blit(*targetCanvas(), pos.topLeft);
}

void StatusWidget::redraw()
{
drawAndShow();
}

void StatusWidget::linkConnected()
{
d->updateTimer->start(1000);
redraw();
}

void StatusWidget::linkDisconnected()
{
d->updateTimer->stop();
redraw();
}

52 changes: 52 additions & 0 deletions doomsday/tools/shell/shell-text/src/statuswidget.h
@@ -0,0 +1,52 @@
/** @file statuswidget.h Widget for status information.
*
* @authors Copyright © 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program 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 2 of the License, or (at your
* option) any later version. This program 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 this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef STATUSWIDGET_H
#define STATUSWIDGET_H

#include <de/shell/TextWidget>
#include <de/shell/Link>

class StatusWidget : public de::shell::TextWidget
{
Q_OBJECT

public:
StatusWidget(de::String const &name = "");
virtual ~StatusWidget();

/**
* Sets the shell Link whose status is to be shown on screen.
*
* @param link Shell connection.
*/
void setShellLink(de::shell::Link *link);

void draw();

public slots:
void redraw();
void linkConnected();
void linkDisconnected();

private:
struct Instance;
Instance *d;
};

#endif // STATUSWIDGET_H

0 comments on commit de17552

Please sign in to comment.