//$Id: DCFileList.cpp,v 1.24 2006/06/05 16:45:38 markus Rel $
//PROJECT : DirComp
//SUBSYSTEM : X-windows
//REFERENCES :
//TODO :
//BUGS :
//REVISION : $Revision: 1.24 $
//AUTHOR : Markus Schwab
//CREATED : 06.02.2003
//COPYRIGHT : Copyright (C) 2003 - 2006
// 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, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <dircomp-cfg.h>
#include <gtkmm/menu.h>
#include <gtkmm/messagedialog.h>
#include <YGP/Check.h>
#include <YGP/Trace.h>
#include <YGP/File.h>
#include <YGP/ATStamp.h>
#include <XGP/XValue.h>
#include "DCFileList.h"
//-----------------------------------------------------------------------------
// (Default-)Constructor
//-----------------------------------------------------------------------------
DCFileList::DCFileList () : files (Gtk::TreeStore::create (cols)) {
TRACE9 ("DCFileList::DCFileList ()");
Check3 (files);
set_model (files);
append_column (Glib::locale_to_utf8 (_("Original time")), cols.timeOrig);
append_column (Glib::locale_to_utf8 (_("Comparative time")), cols.timeComp);
append_column (Glib::locale_to_utf8 (_("Status")), cols.status);
get_column (1)->set_alignment (0.5);
get_column (2)->set_alignment (0.5);
get_column (3)->set_alignment (0.5);
get_column (0)->set_sizing (Gtk::TREE_VIEW_COLUMN_GROW_ONLY);
get_column (1)->set_sizing (Gtk::TREE_VIEW_COLUMN_GROW_ONLY);
get_column (2)->set_sizing (Gtk::TREE_VIEW_COLUMN_GROW_ONLY);
get_column (3)->set_sizing (Gtk::TREE_VIEW_COLUMN_GROW_ONLY);
get_column (0)->set_min_width (245);
get_column (1)->set_min_width (120);
get_column (2)->set_min_width (120);
get_column (3)->set_min_width (50);
get_column (0)->set_resizable ();
get_column (1)->set_resizable ();
get_column (2)->set_resizable ();
get_column (3)->set_resizable ();
}
//-----------------------------------------------------------------------------
/// Destructor
//-----------------------------------------------------------------------------
DCFileList::~DCFileList () {
}
//-----------------------------------------------------------------------------
/// Retrieves the file name of the passed line; which is considered to be
/// stored within the data of the listbox
/// \param line: Line in list to get the filename from
/// \returns std::string: Filename
//-----------------------------------------------------------------------------
std::string DCFileList::getFilename (const Gtk::TreeIter& line) const {
TRACE9 ("DCFileList::getFilename (const Gtk::TreeIter&)");
Check3 (files);
const Gtk::TreeRow row (*line);
YGP::File* pFile (row[cols.fileOrig] ? row[cols.fileOrig] : row[cols.fileComp]);
Check3 (pFile);
return std::string (pFile->path ()) + std::string (pFile->name ());
}
//-----------------------------------------------------------------------------
/// Sets the file which is displayed in the specified line
/// \param line: Line in list to get the filename from
/// \param file: File to display in the line
//-----------------------------------------------------------------------------
void DCFileList::setFilename (Gtk::TreeIter& line, const std::string& file) {
TRACE9 ("DCFileList::setFilename (Gtk::TreeIter, const std::string&) - " << file);
Check3 (files);
Gtk::TreeRow row (*line);
YGP::File* objFile (new YGP::File (file.c_str ()));
row[cols.fileOrig] ? delete row[cols.fileOrig] : delete row[cols.fileComp];
row[cols.fileOrig] ? row[cols.fileOrig] : row[cols.fileComp] = objFile;
XFileList::setFilename (line, file);
}
//-----------------------------------------------------------------------------
/// Adds further menus to the default popup-menu
/// \param menu: Menu where to add some entries to
/// \param line: Line for which to add entries
//-----------------------------------------------------------------------------
void DCFileList::addMenus (Gtk::Menu& menu, const Gtk::TreeIter& line) {
TRACE5 ("DCFileList::addMenus (menu, unsigned int) - " << files->get_path (line).to_string ());
Check3 (files);
const Gtk::TreeRow row (*line);
if (row[cols.fileOrig] && row[cols.fileComp]) {
menu.items ().push_back (Gtk::Menu_Helpers::SeparatorElem ());
#if HAVE_DIFF == 1
menu.items ().push_back
(Gtk::Menu_Helpers::MenuElem
(Glib::locale_to_utf8 (_("Compare with diff ...")),
bind (mem_fun (*this, &DCFileList::startDiff), line)));
#endif
#if HAVE_XXDIFF == 1
menu.items ().push_back
(Gtk::Menu_Helpers::MenuElem
(Glib::locale_to_utf8 (_("Compare with xxdiff ...")),
bind (mem_fun (*this, &DCFileList::execute), "xxdiff", line)));
#endif
#if HAVE_KOMPARE == 1
menu.items ().push_back
(Gtk::Menu_Helpers::MenuElem
(Glib::locale_to_utf8 (_("Compare with Kompare ...")),
bind (mem_fun (*this, &DCFileList::execute), "kompare", line)));
#endif
#if (HAVE_DIFF == yes) || (HAVE_XXDIFF == yes) || (HAVE_KOMPARE == yes)
menu.items ().push_back (Gtk::Menu_Helpers::SeparatorElem ());
#endif
menu.items ().push_back
(Gtk::Menu_Helpers::MenuElem
(Glib::locale_to_utf8 (_("Copy original to comparison")),
bind (mem_fun (*this, &DCFileList::execute), "cp", line)));
menu.items ().push_back
(Gtk::Menu_Helpers::MenuElem
(Glib::locale_to_utf8 (_("Copy comparison to original")),
bind (mem_fun (*this, &DCFileList::execute2), "cp", line)));
}
}
//-----------------------------------------------------------------------------
/// Starts the diff-program in its own terminal
/// \param posObject: Position of files in the listbox
//-----------------------------------------------------------------------------
void DCFileList::startDiff (const Gtk::TreeIter& line) {
const char* term (getenv ("TERM"));
const char* pager (getenv ("PAGER"));
if (term && pager) {
Check3 (files);
const Gtk::TreeRow row (*line);
Check3 (row[cols.fileOrig] && row[cols.fileComp]);
YGP::File* pFile (row[cols.fileOrig]);
std::string orig (std::string (pFile->path ())
+ std::string (pFile->name ()));
pFile = (row[cols.fileComp]);
std::string comp (std::string (pFile->path ())
+ std::string (pFile->name ()));
std::string cmd ("diff ");
cmd += orig;
cmd += ' ';
cmd += comp;
cmd += "|$PAGER ";
TRACE9 ("DCFileList::startDiff (unsigned int) - Cmd: " << cmd);
const char* args[] = { term, "-T", cmd.c_str (), "-e", "sh", "-c",
cmd.c_str (), NULL };
execProgram (term, args, false);
}
else {
Glib::ustring err (Glib::locale_to_utf8 (_("Environment variable `%1' not defined!")));
err.replace (err.find ("%1"), 2, (term ? "PAGER" : "TERM"));
Gtk::MessageDialog dlg (err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
dlg.run ();
}
}
//-----------------------------------------------------------------------------
/// Starts the passed program, passing original and comparision
/// \param file: File to execute
/// \param posObject: Position of files in the listbox
//-----------------------------------------------------------------------------
void DCFileList::execute (const char* file, const Gtk::TreeIter& line) {
Check3 (files);
const Gtk::TreeRow row (*line);
Check3 (row[cols.fileOrig] && row[cols.fileComp]);
YGP::File* pFile (row[cols.fileOrig]);
std::string orig (std::string (pFile->path ())
+ std::string (pFile->name ()));
pFile = (row[cols.fileComp]);
std::string comp (std::string (pFile->path ())
+ std::string (pFile->name ()));
const char* args[] = { file, orig.c_str (), comp.c_str (), NULL };
execProgram (args[0], args, false);
}
//-----------------------------------------------------------------------------
/// Starts the passed program, passing comparision and original
/// \param file: File to execute
/// \param posObject: Position of files in the listbox
//-----------------------------------------------------------------------------
void DCFileList::execute2 (const char* file, const Gtk::TreeIter& line) {
Check3 (files);
const Gtk::TreeRow row (*line);
Check3 (row[cols.fileOrig] && row[cols.fileComp]);
YGP::File* pFile (row[cols.fileOrig]);
std::string orig (std::string (pFile->path ())
+ std::string (pFile->name ()));
pFile = (row[cols.fileComp]);
std::string comp (std::string (pFile->path ())
+ std::string (pFile->name ()));
const char* args[] = { file, comp.c_str (), orig.c_str (), NULL };
execProgram (args[0], args, false);
}
//-----------------------------------------------------------------------------
/// Appends a directory as last parent-entry of the listbox
/// \param dir: Name of the directory to add
//-----------------------------------------------------------------------------
void DCFileList::appendDirectory (const std::string& dir) {
TRACE9 ("DCFileList::appendDirectory (const std::string&) - " << dir);
Check1 (dir.size ());
if (directories.find (dir) == directories.end ()) {
Gtk::TreeIter iter (files->append ());
directories[dir] = iter;
Gtk::TreeModel::Row row (*iter);
row[cols.name] = dir;
row[cols.fileOrig] = NULL;
row[cols.fileComp] = NULL;
}
}
//-----------------------------------------------------------------------------
/// Appends a file to the last parent-entry of the listbox
/// \param prefix: String to prepend filenames with
/// \param orig: Pointer to original file (or NULL)
/// \param comp: Pointer to compared file (or NULL)
/// \param stat: String describing the difference
//-----------------------------------------------------------------------------
void DCFileList::appendFile (const std::string& prefix, const YGP::File* orig,
const YGP::File* comp, const std::string& stat) {
Check1 (orig || comp); Check1 (!stat.empty ());
const YGP::File* pFile (orig ? orig : comp); Check3 (pFile);
const char* pName (pFile->name ());
TRACE3 ("DCFileList::appendFile (const string&, const YGP::File* (2x), const string&) - " << prefix << ": " << pName);
// Add file(s) to the fitting node or as root-entry, if prefix is empty
Check3 (files);
Gtk::TreeIter iter;
if (prefix.size ()) {
Check1 (directories.find (prefix) != directories.end ());
iter = (files->append (directories[prefix]->children ()));
}
else
iter = (files->append ());
Gtk::TreeModel::Row row (*iter);
row[cols.icon] = XGP::XFileList::getIcon4File (*pFile);
row[cols.name] = Glib::filename_to_utf8 (pName);
// Store node, if its a directory
if (pFile->isDirectory ()) {
std::string dir (prefix);
dir += pFile->name ();
dir += YGP::File::DIRSEPARATOR;
TRACE9 ("DCFileList::appendFile (const string&, const YGP::File* (2x), const string&) - Add dir " << dir)
Check2 (directories.find (dir) == directories.end ());
directories[dir] = iter;
}
if (orig) {
YGP::ATimestamp t (orig->time (), false);
row[cols.timeOrig] = t.toString ();
}
if (comp) {
YGP::ATimestamp t (comp->time (), false);
row[cols.timeComp] = t.toString ();
}
row[cols.status] = stat;
row[cols.fileOrig] = orig ? new YGP::File (*orig) : NULL;
row[cols.fileComp] = comp ? new YGP::File (*comp) : NULL;
}
//-----------------------------------------------------------------------------
/// Callback while deleting a row
/// \param row: Row to delete
//-----------------------------------------------------------------------------
void DCFileList::deleteRow (const Gtk::TreeIter& row) {
TRACE1 ("DCFileList::deleteRow (const Gtk::TreeModel::Iter&) - " << getFilename (row));
while (row->children ().size ())
deleteRow (row->children ().begin ());
Gtk::TreeRow irow (*row);
delete irow[cols.fileOrig];
delete irow[cols.fileComp];
irow[cols.fileOrig] = NULL;
irow[cols.fileComp] = NULL;
files->erase (row);
}
//-----------------------------------------------------------------------------
/// Deletes all lines from the model, while caring about freeing the files
//-----------------------------------------------------------------------------
void DCFileList::clear () {
while (files->children ().size ())
deleteRow (files->children ().begin ());
}
syntax highlighted by Code2HTML, v. 0.9.1