/*
* Paulo Pinto (pjmlp_pt@yahoo.com) (c) 2001
* An GUI version of the wc program
*/
#include <gtk--/label.h>
#include <gtk--/fileselection.h>
#include <gnome--/main.h>
#include <gnome--/app.h>
#include <gnome--/stock.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cctype>
//Bring the slot binding command to global scope
using SigC::slot;
// Application
// A minimalist graphical view of wc
class GWCApp: public Gnome::App {
public:
GWCApp ();
virtual ~GWCApp ();
protected:
gint delete_event_impl (GdkEventAny*);
//Signal handlers:
virtual void on_menu_open ();
void process_file ();
private:
bool count_words (const std::string &filename, int &words,
int &lines, int &bytes);
void init_menus ();
void init_toolbar ();
Gtk::Label *m_text;
Gtk::FileSelection *m_filesel;
};
// The program entry point.
// Just create a GWCApp instance and
// launch it.
// Please note that in ANSI C++ the
// return is optional
int main (int argc, char *argv [])
{
// Initialize the framework
Gnome::Main kit ("gwc", "0.0.1", argc, argv);
GWCApp app;
// Make the window appear
app.show ();
// Enter into the event loop
kit.run ();
}
GWCApp::GWCApp ():
Gnome::App ("gwc", "GWC")
{
// Create the text label for showing the word count
m_text = new Gtk::Label ("No file counted");
// Set the window contents. Please note that
// m_text must be deleted explicitly.
// It is deleted in GWCApp::~GWCApp ()
set_contents (*m_text);
// Create the dialog box for opening files
// We don't need to create it here but this
// is just for ilustrive purposes.
m_filesel = manage (new Gtk::FileSelection ("Open File"));
// Connect the ok_button to file_ok_sel function
m_filesel->get_ok_button()->clicked.connect(slot(this,
&GWCApp::process_file));
// Connect the cancel_button to hide the window
m_filesel->get_cancel_button()->clicked.connect
(m_filesel->hide.slot());
init_menus ();
init_toolbar ();
}
GWCApp::~GWCApp ()
{
// Delete the label. We don't need to delete
// the file selection because it is handled
// by manage.
delete m_text;
}
// Creates the application menus
void GWCApp::init_menus ()
{
// Create a file menu using helper functios.
// There are other ways of building menus but this
// is the easiest.
using namespace Gnome;
using namespace Gtk::Menu_Helpers;
// Entries for the file submenu
UI::Info file_menu[] = { MenuItems::Open (slot (this,
&GWCApp::on_menu_open)),
UI::Separator(),
MenuItems::Exit(Gtk::Main::quit.slot ())
};
// This is the for the menu toolbar
UI::SubTree menus[] = { Menus::File(file_menu) };
// Create and attach the menus to the
// application window
create_menus(menus);
}
// Creates the application toolbar
void GWCApp::init_toolbar ()
{
// Create a toolbar using helper functios.
using namespace Gnome;
UI::Info toolbar[] = {UI::Item(UI::Icon(GNOME_STOCK_PIXMAP_OPEN),
"Open", slot(this,
&GWCApp::on_menu_open),
"Open a file"),
UI::Separator (),
UI::Item(UI::Icon(GNOME_STOCK_PIXMAP_EXIT),
"Exit", Gtk::Main::quit.slot (),
"Exit the application")
};
// Create and attach the toolbar to the
// application window
create_toolbar(toolbar);
}
// Called when the user presses the 'X' mark
// on the window.
// Redefining this method is another way of
// receiving the 'delete' signal.
gint GWCApp::delete_event_impl(GdkEventAny*)
{
Gtk::Main::quit();
return FALSE;
}
// Called when the user selects the
// File->Open option
void GWCApp::on_menu_open ()
{
m_filesel->set_modal (true);
m_filesel->show ();
}
// Called when the user presses the
// Ok button on the FileSelection dialog
void GWCApp::process_file ()
{
m_filesel->hide ();
std::string filename = m_filesel->get_filename ();
int words, lines, bytes;
std::ostringstream msg;
// Clear and force a redraw, or else
// the older string will appear
m_text->set_text ("");
draw (0);
if (!count_words (filename, words, lines, bytes)) {
msg << "Couldn't open " << filename;
Gnome::Dialogs::error (msg.str ());
}
else {
msg << "The file " << filename;
msg << ", has " << lines << " lines, " << words << " words and ";
msg << bytes << " bytes." ;
m_text->set_text (msg.str ());
}
}
// Counts all the words, lines and bytes.
// This isn't the most eficient way to do it, but
// it servers the purpose of the example.
bool GWCApp::count_words (const std::string &filename, int &words,
int &lines, int &bytes)
{
std::ifstream in (filename.c_str ());
if (!in)
return false;
words = 0;
lines = 0;
bytes = 0;
char ch;
while (!in.eof ()) {
// Advance the file pointer to the next
// word
do {
in.get (ch);
if (!in.eof ()){
bytes++;
// Ok, now changing for the next line
if (ch == '\n')
lines++;
}
} while (!in.eof () && isspace (ch));
// Advance the file pointer to the next
// white space
if (!in.eof ()) {
words++;
do {
in.get (ch);
if (!in.eof ())
bytes++;
} while (!in.eof () && !isspace (ch));
}
}
return true;
}
End of Listing