//$Id: XDirComp.cpp,v 1.65 2007/03/22 19:26:13 markus Rel $
//PROJECT : XDirComp
//SUBSYSTEM : XDirComp
//REFERENCES :
//TODO :
//BUGS :
//REVISION : $Revision: 1.65 $
//AUTHOR : Markus Schwab
//CREATED : 27.8.1999
//COPYRIGHT : Copyright (C) 1999 - 2007
// 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 <cerrno>
#include <unistd.h>
#include <limits.h>
#include <sys/stat.h>
#include <fstream>
#include <iomanip>
#define CONVERT_TO_UTF8
#include <dircomp-cfg.h>
#ifdef ENABLE_THREADS
# include <glib.h>
#endif
#include <gtkmm/stock.h>
#include <gtkmm/toggleaction.h>
#include <gtkmm/messagedialog.h>
#include <YGP/Check.h>
#include <YGP/Trace.h>
#include <YGP/File.h>
#include <YGP/SmartPtr.h>
#include <YGP/ANumeric.h>
#include <YGP/PathSrch.h>
#include <YGP/RDirSrch.h>
#include <YGP/PathDirSrch.h>
#include <XGP/XDate.h>
#include <XGP/XAbout.h>
#include <XGP/XFileDlg.h>
#include <XGP/XPrintDlg.h>
#include "XFileSel.h"
#include "XDirComp.h"
static const int DEFAULTPORT = (31336U);
// Pixmap for program
const char* XDirComp::xpmXDirComp[] = {
"56 46 38 1",
" c None",
". c #FFFFFF",
"+ c #D7D3D7",
"@ c #000000",
"# c #E7E7EF",
"$ c #515549",
"% c #969696",
"& c #AEAAAE",
"* c #AEA6AE",
"= c #AEAEAE",
"- c #A69EA6",
"; c #B6AEB6",
"> c #616161",
", c #A6A2A6",
"' c #AEAEB6",
") c #717571",
"! c #BEB6BE",
"~ c #CFC7CF",
"{ c #303430",
"] c #000808",
"^ c #696971",
"/ c #EFF3F7",
"( c #202020",
"_ c #182020",
": c #080408",
"< c #8E8A8E",
"[ c #BEC3BE",
"} c #9E9A9E",
"| c #D7DFE7",
"1 c #79869E",
"2 c #AE9E59",
"3 c #282C30",
"4 c #BEBABE",
"5 c #AE6161",
"6 c #51A249",
"7 c #E7D79E",
"8 c #BEC3CF",
"9 c #8E8679",
"......................................................+@",
"..+++++++++++++++++++++++++++++++++++++++++++++++++++#$@",
"..%&*=%**%**%**%**%**%**%**%**%**%**%**%**%**%**%**=-;>@",
"..,**&&=&&=&'*=&=&'*=&=&'*=&=&'*=&=&'*=&=&'*=&=&'=*==')@",
"..-==&&&&&&&&=&&&&&=&&&&&=&&&&&=&&&&&=&&&&&=&&&&&&=&=!)@",
"..-&&&&&&&&&&&&&&&&&&----------&=!~!~~~!;&&&&&&&&&&&=')@",
"..,&&&&&&&&&&&&&&&&~............#)@{@]@$=&&&&&&&&&&&&!^@",
"..&&&&&&&&&&&&&&=!'/............#,(@@@@('!&&&&&&&&&&=!)@",
"..-&&&;&;&;&&;&!~=$)^$>$$........~{({]@@)&&&&;&&;&&&&;)@",
"..-&&&&&&&&&&'!=@@@{{{{{{_@@.....+@@@@@@$!'!&&&&&&&&==)@",
"..,&&&!*=&&..+_@$$$$))_@@($$@{+...~(]@:@{$!=&&;&&&&&&!)@",
"..&&&=*=&&=.<@@$$==+#[<$=~=&=@@=..!@@@@@@@~;&&&&&;&==;)@",
"..-&&&=&&;!$_$$#/...'$$$&=...+}@).;]@:@:@@)!==&&&&&&=!^@",
"..-&&&;&=~@{$>......|)$$}}.....+@1/$@@@@@@$=;;&&&&&==;)@",
"..,&&&&&!)_${.......#=$_(@!;....~@(@@:@:@@@$};==&&&&=!)@",
"..&&&&=;~_{$~.....=<)@({@@$$<<}..)@@@@:@]@@_>1!&&&&==;)@",
"..-&&&&!)@{{...#='}$@@{$@@$$$$$$}&@@:@@:@@@@@(;!=&&&&;)@",
"..-&&&=;{{$)..#,=;)@@@@@@@$$$$$$$$(:@@:@@:]@@]>;&&&===)@",
"..,&&&=~{{$..}===!^:@:((}&!~{{${$${@@:@@:@@@@@_};=&&=!)@",
"..&&&='!{{$/^{;=-;}$(@{$#...#.#+$$(@:@@:@@:]@@@$!!&==;)@",
"..-&&&&[{{$$$$[=+.~$$>]]+.......+$_:@$:@@:@@]@@]1====!^@",
"..-&&&'!{{$((@<!~++<>}{@$)^)*,+~[)(@@{@@:@@:@]@@)!!==!)@",
"..,=&&&;)@$@@@$&=*=*=~$@@@@@$$'!')@@:@:@@:@@:@@@@);==;$@",
"..&&&&==;{{>$);..,*&,)$$$$$$@@$^/(@@@:@@:@$@@)#%@$!===)@",
"..-&&&&=!)_$$~+.#=!+<^}=&=)<^)==}@@:@@:@(~$$)!..$$;==!)@",
"..-=&&=!!;$@1...#$2~+~....~=.../@{@@:@@:@);....#$$!==;)@",
"..-=&&====[@{$$...=]@@@@@@}}.#+_@((@@:@@&.#....+$$===!^@",
"..-&&=;===';@@3+..+${@{{$$~+.@@{@)):@(&~..!~.+~,$$!==!)@",
"..,=&&&&&;&.#{@@'...~{%!....$@@,<3{@@:@,....#=.~@$;==;)@",
"..&&;&&&&&,..$$]@@@$=..}$@@@@$@@^}(:@{}.;.=...+(]$;==;)@",
"..-&&&&&&&&+#.$$($@]@@@@@@$]{{(@:$;$).......~#$@@>'==!^]",
"..-&&&&&&&=&}+!$$$$${${(($@$<});@@,#&<#+...+.=@(@$[===)@",
"..,=&&;&&&-#;')#$$$$<;)$+.....>)$((,#[)#!.;.,@{@@>'==!)@",
"..-&&&&=;}.+42%/~{$$3)<%<1<<({{$$>{]^/~)1=.)_@$@@$!&==)@",
"..-=&&&!}<1<)@@@@@@@@@]@@@@@@@]@({$$@$+#)^$@@@(@@>'=&!)@",
"..=*=!!-((@@@@@@@@]@]@]@@@@@$@:@@@@@@]$~.=@@@]@@])!==;)@",
"..-=!%{@@@@@@]@:@:@@@@@]@:@@$$@@@@@@@@@_}.~$:@:@@$!==!)@",
"..-;}(@@@@@@]@@]@@:@:@:@@@:@:@:@:]@]@@@@@).+)@@@@$;==!^@",
"..};}^))51))^)6))))1)^51))))6))51)^))${{{@)~~+$<)}!==;)@",
"..==;;![;!;;!!;!4;!=;!!!;;;;!'4!=!;!;!)$$$@)#{{=!;====)@",
"..-===&===============================!)$$$@]@{!=====!)@",
"..-*=&&&&&====&&*==&==========&========;}$$${)=;=&===;)@",
"..-=&=&&&&=!=*&&;===&=*==!=*=;&&=&&&&===!=$$$$)!===&=!^@",
"..=!;!;;;!;;;;!;;;!!;!;!;;!;!!;!!;!;!;!!'!7'887=;!;!=+)@",
"..)<1<<1<191<191<191<<<19191<191<191<191<1112111<191<1^]",
"#{@@@@@]@@]@]@]@@@@@@@@@@@@@@@@@@@@@@@@@@@]@]@]]@@@@@::@" };
// Pixmap for author
const char* XDirComp::xpmAuthor[] = {
"56 43 5 1",
" c None",
"! c #0000FF",
"@ c #000000",
"- c #AEAAAE",
". c #FFFFFF",
".......................................................@",
"..-----------------------------------------------------@",
"..-----------------------------------------------------@",
"..----------------------!!!!!!-------------------------@",
"..--------------------!!!!@@!!!!-----------------------@",
"..------------------!!!!@@---@@!!!---------------------@",
"..-----------------!!!@@--------!!!--------------------@",
"..-----------------!!!@---!!----!!!--------------------@",
"..----------------!!!@---!!!!@---!!!-------------------@",
"..----------------!!@---!!!!!!@---!!@------------------@",
"..----------------!!@----!!!!@----!!@------------------@",
"..----------------!!!-----!!@----!!!@------------------@",
"..-----------------!!!-----@-----!!!@------------------@",
"..-----------------!!!!---------!!!@-------------------@",
"..------------------!!!!-------!!!@--------------------@",
"..--------------------!!!!--!!!!@@---------------------@",
"..----------------------!!!!!!@@-----------------------@",
"..-----------------------!!!!@-------------------------@",
"..------------------------!!@--------------------------@",
"..------------------------!!@--------------------------@",
"..------------------!!!!!!!!!!!!!!---------------------@",
"..-----------------!!!!!!!!!!!!!!!!--------------------@",
"..----------------!!!@@@@@!!@@@@@!!!-------------------@",
"..----------------!!@-----!!@-----!!@------------------@",
"..----------------!!@-----!!@-----!!@------------------@",
"..----------------!!@-----!!@-----!!@------------------@",
"..----------------!!@-----!!@-----!!@------------------@",
"..-----------------@@-----!!@------@@------------------@",
"..------------------------!!@--------------------------@",
"..--------------------!!!!!!!!!!-----------------------@",
"..------------------!!!!!!!!!!!!!!---------------------@",
"..-----------------!!!@@@@@@@@@!!!!--------------------@",
"..-----------------!!@----------!!!!-------------------@",
"..----------------!!!@-----------!!!@------------------@",
"..----------------!!@------------!!!@------------------@",
"..----------------!!@-------------!!@------------------@",
"..----------------!!@-------------!!@------------------@",
"..----------------!@--------------!!@------------------@",
"..----------------!!@--------------@@------------------@",
"..-----------------!@----------------------------------@",
"..------------------@----------------------------------@",
"..-----------------------------------------------------@",
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" };
//-----------------------------------------------------------------------------
/// Defaultconstructor; all widget are created
//-----------------------------------------------------------------------------
XDirComp::XDirComp ()
: XApplication ("X" PACKAGE " V" PRG_RELEASE)
, tblInput (2, 2), inDirComp (YGP::DirectorySearch::FILE_DIRECTORY)
, inDirOrig (YGP::DirectorySearch::FILE_DIRECTORY)
, lblDirOrig (Glib::locale_to_utf8 (_("Original directory:")))
, lblDirComp (Glib::locale_to_utf8 (_("Comparative directory:")))
, listFiles () , status (), scroll ()
#ifdef ENABLE_THREADS
, dc (listFiles, status, (YGP::Thread*)(childSearch))
, childSearch (NULL)
#else
, dc (listFiles, status)
#endif
, dateStart (time_t (0)) , dateEnd (time_t (INT_MAX)) {
TRACE1 ("XDirComp::XDirComp ()");
setIconProgram (xpmXDirComp);
set_default_size (620, 400);
Glib::ustring ui ("<ui><menubar name='Menu'>"
" <menu action='Dir'>"
" <menuitem action='Start'/>"
" <menuitem action='EndComp'/>"
" <separator/>"
" <menuitem action='Save'/>"
" <menuitem action='Print'/>"
" <separator/>"
" <menuitem action='Quit'/>"
" </menu>"
" <menu action='Options'>"
" <menuitem action='ShowNew'/>"
" <menuitem action='ShowChg'/>"
" <menuitem action='ShowEqual'/>"
" <menuitem action='ShowChgDirs'/>"
" <menuitem action='ShowHidden'/>"
" <separator/>"
" <menuitem action='SrchDirs'/>"
" <menuitem action='SrchEqualDirs'/>"
" <separator/>"
" <menuitem action='Comp'/>"
" <menuitem action='CompAll'/>"
" <separator/>"
" <menuitem action='SelFiles'/>"
" <menuitem action='SelDirs'/>"
" <separator/>"
" <menuitem action='StartDate'/>"
" <menuitem action='EndDate'/>"
" </menu>");
grpAction->add (Gtk::Action::create ("Dir", _("_Directory")));
grpAction->add (apMenus[START] = Gtk::Action::create ("Start", _("_Start compare")),
Gtk::AccelKey (_("<ctl>s")),
mem_fun (*this, &XDirComp::startCompare));
grpAction->add (apMenus[STOP] = Gtk::Action::create ("EndComp", Gtk::Stock::CLOSE,
_("S_top compare")),
Gtk::AccelKey (_("<ctl>Break")),
mem_fun (*this, &XDirComp::endCompare));
grpAction->add (Gtk::Action::create ("Quit", Gtk::Stock::QUIT),
mem_fun (*this, &XDirComp::quit));
grpAction->add (apMenus[SAVE] = Gtk::Action::create ("Save", Gtk::Stock::SAVE),
Gtk::AccelKey (_("F2")),
mem_fun (*this, &XDirComp::save));
grpAction->add (apMenus[PRINT] = Gtk::Action::create ("Print", Gtk::Stock::PRINT),
mem_fun (*this, &XDirComp::print));
grpAction->add (Gtk::Action::create ("Options", _("_Options")));
grpAction->add (Gtk::ToggleAction::create ("ShowNew", _("Show _new"), "", true),
Gtk::AccelKey (_("<ctl>N")),
bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_NONEWDEL));
grpAction->add (Gtk::ToggleAction::create ("ShowChg", _("Show _changed files"),
"", true),
Gtk::AccelKey (_("<alt><ctl>N")),
bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_NOCHANGED));
grpAction->add (Gtk::ToggleAction::create ("ShowEqual", _("Show _equal files")),
Gtk::AccelKey (_("<ctl>E")),
bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_EQUAL));
grpAction->add (Gtk::ToggleAction::create ("ShowChgDirs", _("Show _changed dirs")),
Gtk::AccelKey (_("<alt><ctl>D")),
bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_NODIRCOMP));
grpAction->add (Gtk::ToggleAction::create ("ShowHidden", _("Show _hidden files")),
Gtk::AccelKey (_("<alt><ctl>H")),
bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_CHECKHIDDEN));
grpAction->add (apMenus[SUBDIRS] = Gtk::ToggleAction::create ("SrchDirs", Gtk::Stock::GOTO_LAST,
_("Search _subdirs")),
Gtk::AccelKey (_("<alt><ctl>S")),
mem_fun (*this, &XDirComp::searchSubdirs));
grpAction->add (apMenus[EQUALSUBDIRS] = Gtk::ToggleAction::create ("SrchEqualDirs", _("Search _equal subdirs")),
Gtk::AccelKey (_("<alt><ctl>Q")),
mem_fun (*this, &XDirComp::searchEqualSubdirs));
grpAction->add (apMenus[COMPARE] = Gtk::ToggleAction::create ("Comp", Gtk::Stock::FIND,
_("Compare c_ontents")),
Gtk::AccelKey (_("<ctl>C")),
bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_CHECKCONTENTS));
grpAction->add (Gtk::ToggleAction::create ("CompAll", _("Compare _always")),
Gtk::AccelKey (_("<alt><ctl>C")),
mem_fun (*this, &XDirComp::compareAlways));
grpAction->add (Gtk::Action::create ("SelFiles", _("Select _files ...")),
Gtk::AccelKey (_("<ctl>F")),
mem_fun (*this, &XDirComp::selectFiles));
grpAction->add (Gtk::Action::create ("SelDirs", _("Select d_irectories ...")),
Gtk::AccelKey (_("<alt><ctl>F")),
mem_fun (*this, &XDirComp::selectDirectories));
grpAction->add (Gtk::Action::create ("StartDate", _("_Lower date-border ...")),
Gtk::AccelKey (_("<ctl>T")),
bind (mem_fun (*this, &XDirComp::selectDate), false));
grpAction->add (Gtk::Action::create ("EndDate", _("_Upper date-border ...")),
Gtk::AccelKey (_("<alt><ctl>T")),
bind (mem_fun (*this, &XDirComp::selectDate), true));
addHelpMenu (ui);
ui += "</menubar></ui>";
mgrUI->insert_action_group (grpAction);
add_accel_group (mgrUI->get_accel_group ());
mgrUI->add_ui_from_string (ui);
((Gtk::MenuItem*)(mgrUI->get_widget("/Menu/Help")))->set_right_justified ();
getClient ()->pack_start (*mgrUI->get_widget("/Menu"), Gtk::PACK_SHRINK);
// Disable menus according to state of program
apMenus[START]->set_sensitive (false);
apMenus[STOP]->set_sensitive (false);
apMenus[SAVE]->set_sensitive (false);
apMenus[PRINT]->set_sensitive (false);
// Create controls
tblInput.show ();
vboxClient->pack_start (tblInput, false, true, 5);
lblDirOrig.set_alignment (0.0, 0.5);
lblDirOrig.show ();
tblInput.attach (lblDirOrig, 0, 1, 0, 1, Gtk::FILL,
Gtk::EXPAND | Gtk::FILL, 5);
lblDirComp.set_alignment (0.0, 0.5);
lblDirComp.show ();
tblInput.attach (lblDirComp, 0, 1, 1, 2, Gtk::FILL,
Gtk::EXPAND | Gtk::FILL, 5, 5);
inDirComp.show ();
inDirComp.signal_changed ().connect (mem_fun (*this, &XDirComp::dirChanged));
tblInput.attach (inDirComp, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL,
Gtk::EXPAND | Gtk::FILL, 5, 5);
inDirOrig.show ();
inDirOrig.signal_changed ().connect (mem_fun (*this, &XDirComp::dirChanged));
tblInput.attach (inDirOrig, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL,
Gtk::EXPAND | Gtk::FILL, 5);
listFiles.get_selection ()->set_mode (Gtk::SELECTION_EXTENDED);
listFiles.show ();
scroll.add (listFiles);
scroll.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
vboxClient->pack_start (scroll);
scroll.show ();
status.push (Glib::locale_to_utf8 (_("Enter directories to compare")));
status.show ();
vboxClient->pack_start (status, Gtk::PACK_SHRINK);
show ();
inDirOrig.grab_focus ();
}
//-----------------------------------------------------------------------------
/// Callback to actually compare the two directories (incl. GUI-changes)
//-----------------------------------------------------------------------------
void* XDirComp::compare (YGP::Thread*) {
TRACE5 ("XDirComp::compare (YGP::Thread*)");
try {
dc.compare ();
listFiles.expand_all ();
}
catch (...) { }
#ifdef ENABLE_THREADS
gdk_threads_enter ();
#endif
listFiles.finish ();
status.pop ();
status.push (getDifferentFiles ());
apMenus[SAVE]->set_sensitive (true);
apMenus[PRINT]->set_sensitive (true);
#ifdef ENABLE_THREADS
childSearch = NULL;
#endif
menuInSearch (false);
#ifdef ENABLE_THREADS
gdk_threads_leave ();
#endif
delete dc.getOrigObject ();
delete dc.getCompObject ();
return NULL;
}
//-----------------------------------------------------------------------------
/// Builds a string with the number of changed files
//Returns : Text with changed files
//-----------------------------------------------------------------------------
std::string XDirComp::getDifferentFiles () const {
TRACE9 ("XDirComp::getDifferentFiles (): Files found: "
<< listFiles.rows () << "; Changed: "
<< dc.getChangedFiles () << "; New: " << dc.getNewFiles ());
YGP::ANumeric numFiles (dc.getNumFiles ());
YGP::ANumeric numChg (dc.getChangedFiles ());
YGP::ANumeric numNew (dc.getNewFiles ());
std::string stat (ngettext ("%1 file", "%1 files", numFiles));
stat.replace (stat.find ("%1"), 2, numFiles.toString ());
std::string chg (Glib::locale_to_utf8 (_("; %1 new, %2 changed")));
chg.replace (chg.find ("%1"), 2, numNew.toString ());
chg.replace (chg.find ("%2"), 2, numChg.toString ());
return stat + chg;
}
//-----------------------------------------------------------------------------
/// Starts the comparison
//-----------------------------------------------------------------------------
void XDirComp::startCompare () {
TRACE9 ("XDirComp::startCompare ()");
YGP::IDirectorySearch* dirs[2];
XGP::XFileEntry* dirNames[2] = { &inDirOrig, &inDirComp };
Check3 ((sizeof (dirs) / sizeof (dirs[0]))
== (sizeof (dirNames) / sizeof (dirNames[0])));
for (unsigned int i (0); i < (sizeof (dirs) / sizeof(dirs[0])); ++i) {
try {
dirs[i] = CompareDirs::makeSearchobject (dirNames[i]->get_text ().c_str (),
DEFAULTPORT);
}
catch (std::exception& e) {
std::string error (Glib::locale_to_utf8 (_("Error accessing directory"
" '%1'\nReason: %2")));
error.replace (error.find ("%1"), 2, dirNames[i]->get_text ());
error.replace (error.find ("%2"), 2, e.what ());
Gtk::MessageDialog (error, false, Gtk::MESSAGE_ERROR,
Gtk::BUTTONS_OK).run ();
dirNames[i]->grab_focus ();
return;
}
Check3 (dirs[i]);
}
TRACE9 ("XDirComp::startCompare () - Cleaning list");
dc.reset ();
TRACE9 ("XDirComp::startCompare () - Setting directories to compare");
dc.setOriginalDir (*dirs[0]);
dc.setCompareDir (*dirs[1]);
if (!dirInExcl.empty ()) { // Set subdir-search if dirs to in/exclude
Check3 (apMenus[SUBDIRS]);
Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic (apMenus[SUBDIRS])->set_active ();
}
TRACE8 ("XDirComp::startCompare () - Files to in/exclude: " << files);
YGP::PathSearch ps (files);
std::string node;
// Handle all existing file-entries
while (!(node = ps.getNextNode ()).empty ()) {
bool include (node[0] == '+');
node.replace (0, 1, 0, '\0');
TRACE5 ((include ? "Including" : "Excluding") << " " << node);
include ? dc.addIncludeFiles (node) : dc.addExcludeFiles (node);
} // end-while
TRACE8 ("XDirComp::command (int) - Dirs to in/exclude: " << dirInExcl);
ps = dirInExcl;
// Handle all existing directory-entries
while (!(node = ps.getNextNode ()).empty ()) {
bool include (node[0] == '+');
node.replace (0, 1, 0, '\0');
TRACE5 ((include ? "Incl. dir" : "Excl. dir") << " " << node);
include ? dc.addIncludeDirs (node) : dc.addExcludeDirs (node);
} // end-while
dc.setBeginTime (dateStart.toSysTime ());
dc.setEndTime (dateEnd.toSysTime ());
menuInSearch (true);
#ifdef ENABLE_THREADS
childSearch = (YGP::OThread<XDirComp>::create
(this, (YGP::OThread<XDirComp>::THREAD_OBJMEMBER)&XDirComp::compare, NULL));
childSearch->allowCancelation ();
#else
compare (NULL);
#endif
}
//-----------------------------------------------------------------------------
/// Ends the comparison
//-----------------------------------------------------------------------------
void XDirComp::endCompare () {
#ifdef ENABLE_THREADS
Check2 (childSearch);
dc.lock ();
childSearch->cancel ();
dc.unlock ();
delete childSearch;
childSearch = NULL;
#endif
menuInSearch (false);
status.pop ();
status.push (Glib::locale_to_utf8 (_("User canceled; "))
+ getDifferentFiles ());
}
//-----------------------------------------------------------------------------
/// Prints the result of the comparison
//-----------------------------------------------------------------------------
void XDirComp::print () {
XGP::PrintDialog::create ()->sigPrint.connect (mem_fun (*this, &XDirComp::writeToStream));
}
//-----------------------------------------------------------------------------
/// Saves the result of the comparison
//-----------------------------------------------------------------------------
void XDirComp::save () {
XGP::FileDialog::create (Glib::locale_to_utf8 (_("Save comparison to ...")),
Gtk::FILE_CHOOSER_ACTION_SAVE,
XGP::FileDialog::ASK_OVERWRITE)
->sigSelected.connect (mem_fun (*this, &XDirComp::saveToFile));
}
//-----------------------------------------------------------------------------
/// Toggles the search-subdirectory flag; If set, reset the equal subdirs
/// option
//-----------------------------------------------------------------------------
void XDirComp::searchSubdirs () {
dc.toggleOption (CompareDirs::OPT_SEARCHSUBDIRS);
if (dc.hasOption (CompareDirs::OPT_SEARCHSUBDIRS))
Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic (apMenus[EQUALSUBDIRS])->set_active (false);
}
//-----------------------------------------------------------------------------
/// Toggles the search-equal--subdirectory flag; If set, reset the subdirs
/// option
//-----------------------------------------------------------------------------
void XDirComp::searchEqualSubdirs () {
dc.toggleOption (CompareDirs::OPT_SEARCHEQUALSUBDIRS);
if (dc.hasOption (CompareDirs::OPT_SEARCHEQUALSUBDIRS))
Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic (apMenus[SUBDIRS])->set_active (false);
}
//-----------------------------------------------------------------------------
/// Checks the compare always option; If set, also set compare
//-----------------------------------------------------------------------------
void XDirComp::compareAlways () {
dc.toggleOption (CompareDirs::OPT_IGNORETIMESTAMP);
Check3 (apMenus[COMPARE]);
Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic (apMenus[COMPARE])->set_active ();
}
//-----------------------------------------------------------------------------
/// Terminates the program
//-----------------------------------------------------------------------------
void XDirComp::quit () {
#ifdef ENABLE_THREADS
if (childSearch) {
childSearch->cancel ();
delete childSearch;
childSearch = NULL;
}
#endif
hide ();
}
//-----------------------------------------------------------------------------
/// Enables selecting the files to compare
/// \param option: Option to toggle
//-----------------------------------------------------------------------------
void XDirComp::toggleOption (XCompareDirs::Options option) {
dc.toggleOption (option);
}
//-----------------------------------------------------------------------------
/// Enables selecting the files to compare
//-----------------------------------------------------------------------------
void XDirComp::selectFiles () {
XFileSelection::create (files, Glib::locale_to_utf8 (_("Select files to compare")));
}
//-----------------------------------------------------------------------------
/// Enables selecting the directories to compare
//-----------------------------------------------------------------------------
void XDirComp::selectDirectories () {
XFileSelection::create (dirInExcl, Glib::locale_to_utf8 (_("Select directories to compare")));
}
//-----------------------------------------------------------------------------
/// Enables selecting the directories to compare
/// \param upper: Flag, if to change the upper or the lower date limit
//-----------------------------------------------------------------------------
void XDirComp::selectDate (bool upper) {
XGP::XDate::create (Glib::locale_to_utf8 (upper ? _("Compare to") : _("Compare from")),
upper ? dateEnd : dateStart);
}
//-----------------------------------------------------------------------------
/// Shows the about box
//-----------------------------------------------------------------------------
void XDirComp::showAboutbox () {
std::string ver (Glib::locale_to_utf8 (_("Copyright (C) 1999 - 2007 "
"Markus Schwab\ne-mail: g17m0@"
"lycos.com\n\nCompiled on %1 at %2")));
ver.replace (ver.find ("%1"), 2, __DATE__);
ver.replace (ver.find ("%2"), 2, __TIME__);
XGP::XAbout* about (XGP::XAbout::create (ver, "X" PACKAGE " V" VERSION));
about->setIconProgram (xpmXDirComp);
about->setIconAuthor (xpmAuthor);
about->get_window ()->set_transient_for (get_window ());
}
//-----------------------------------------------------------------------------
/// Entryfield for directory-path changed -> adapt menu-status
//-----------------------------------------------------------------------------
void XDirComp::dirChanged () {
Check3 (apMenus[START]);
TRACE9 ("XDirComp::dirChanged () - " << inDirOrig.get_text_length () << '/'
<< inDirComp.get_text_length ());
bool inSearch (false);
#ifdef ENABLE_THREADS
inSearch = childSearch;
#endif
apMenus[START]->set_sensitive
(inSearch
? false
: inDirComp.get_text_length () && inDirOrig.get_text_length ());
}
//-----------------------------------------------------------------------------
/// Save result of comparison into a file
/// \param file: Name of file to create
//-----------------------------------------------------------------------------
void XDirComp::saveToFile (const std::string& file) {
TRACE9 ("XDirComp::saveToFile (std::string&): " << file);
FILE* output (fopen (file.c_str (), "w"));
if (!output) {
std::string error (Glib::locale_to_utf8 (_("Can not create file `%1'\n Reason: %2")));
error.replace (error.find ("%1"), 2, file);
error.replace (error.find ("%2"), 2, strerror (errno));
Gtk::MessageDialog dlg (error, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
dlg.run ();
return;
}
writeToStream (output);
fclose (output);
}
//-----------------------------------------------------------------------------
/// Save result of comparison into a file
/// \param file: Stream to fill
//-----------------------------------------------------------------------------
void XDirComp::writeToStream (FILE* file) {
TRACE9 ("XDirComp::writeToStream (std::ostream&)");
Check3 (file);
Glib::ustring t1, t2;
int lenTime (YGP::ATimestamp::now ().toString ().length ());
Glib::ustring fill (lenTime++, ' ');
lenTime <<= 1;
for (unsigned int i (0); i < listFiles.rows (); ++i) {
Gtk::TreeRow row (listFiles.row (i));
std::string filename (row[listFiles.getColumns ().name]);
TRACE8 ("XDirComp::writeToStream (std::ofstream&): " << filename);
fprintf (file, "%-7s: %s", ((Glib::ustring)(row[listFiles.getColumns ().status])).c_str (),
filename.c_str ());
for (unsigned int j (0); j < (69 - filename.size () - lenTime); ++j)
fputc (' ', file);
t1 = row[listFiles.getColumns ().timeOrig];
t2 = row[listFiles.getColumns ().timeComp];
fprintf (file, " %s %s\n", (t1.size () ? t1 : fill).c_str (),
(t2.size () ? t2 : fill).c_str ());
} // end-for all text-columns
}
//-----------------------------------------------------------------------------
/// Sets the menu according the status
/// \param posObject: Position of files in the listbox
//-----------------------------------------------------------------------------
void XDirComp::menuInSearch (bool search) {
apMenus[STOP]->set_sensitive (search);
if (search)
apMenus[START]->set_sensitive (false);
else
dirChanged ();
}
//-----------------------------------------------------------------------------
/// Displays the different file
/// \param diff: Flag how the files differ
/// \param pFileOrig: Original file (NULL if new)
/// \param pFileComp: Compared file (NULL if deleted)
//-----------------------------------------------------------------------------
void XCompareDirs::showFile (const Status diff, const YGP::File* pFileOrig,
const YGP::File* pFileComp) {
TRACE2 ("XCompareDirs::showFile (const Status, 2x const YGP::File*)");
Check3 (diff <= DIR_NEW);
Check3 (((diff == DIR_NEW) ? !pFileOrig : pFileOrig != NULL));
Check3 (((diff == DIR_DELETED) ? !pFileComp : pFileComp != NULL));
static const Glib::ustring apFileStati[] = {
Glib::locale_to_utf8 (_("Younger")),
Glib::locale_to_utf8 (_("Older")),
Glib::locale_to_utf8 (_("Different")),
Glib::locale_to_utf8 (_("Equal")),
Glib::locale_to_utf8 (_("Deleted")),
Glib::locale_to_utf8 (_("New")) };
#ifdef ENABLE_THREADS
gdk_threads_enter ();
lock ();
#endif
TRACE2 ("XCompareDirs::showFile (const Status, 2x const YGP::File*) - Dir: " << getDirStartComp ());
list.appendFile (getDirStartComp (), pFileOrig, pFileComp, apFileStati[diff]);
#ifdef ENABLE_THREADS
unlock ();
gdk_threads_leave ();
#endif
// Adapt number of different files
++cAllFiles;
if (diff < DIR_EQUAL)
++cChangedFiles;
else if (diff > DIR_EQUAL)
++cNewFiles;
#ifdef ENABLE_THREADS
if (thread)
thread->isToCancel ();
#endif
}
//-----------------------------------------------------------------------------
/// Directory changed during compare
/// \param path: Entered directory
//-----------------------------------------------------------------------------
void XCompareDirs::enterDirectory (const std::string& path) {
TRACE7 ("XCompareDirs::enterDirectory (const std::string&) - " << path);
#ifdef ENABLE_THREADS
gdk_threads_enter ();
lock ();
#endif
static bool origEntry (true);
if (origEntry) {
TRACE9 ("XCompareDirs::enterDirectory (const std::string&) - " << getDirStartComp ());
std::string dir (getDirStartComp ());
if (dir.size ())
list.appendDirectory (dir);
}
origEntry = !origEntry;
info.pop ();
std::string str (Glib::locale_to_utf8 (_("Handling directory: %1")));
str.replace (str.find ("%1"), 2, path);
info.push (str);
#ifdef ENABLE_THREADS
unlock ();
gdk_threads_leave ();
if (thread)
thread->isToCancel ();
#endif
}
//-----------------------------------------------------------------------------
/// Clear object for compare (clear list; reset object-counters)
//-----------------------------------------------------------------------------
void XCompareDirs::reset () {
clearFiles ();
clearDirectories (); // Reset in/exclude-info for new compare
cAllFiles = cChangedFiles = cNewFiles = 0;
list.freeze_child_notify ();
list.clear ();
list.thaw_child_notify ();
}
//-----------------------------------------------------------------------------
/// Entrypoint of application
/// \param argc: Number of parameters
/// \param argv: Array with pointer to parameter
//Returns : int: Status
//-----------------------------------------------------------------------------
int main (int argc, char* argv[]) {
TRACE1 ("main (int, char**) - Args: " << argc);
XDirComp::initI18n (PACKAGE, LOCALEDIR);
#ifdef ENABLE_THREADS
Glib::thread_init (NULL);
gdk_threads_init ();
gdk_threads_enter ();
#endif
Gtk::Main appl (argc, argv);
XDirComp win;
appl.run (win);
#ifdef ENABLE_THREADS
gdk_threads_leave ();
#endif
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1