//$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 #include #include #include #include #include #include #include #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 ()); }