//$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 #include #include #include #include #include #define CONVERT_TO_UTF8 #include #ifdef ENABLE_THREADS # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 ("" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "); grpAction->add (Gtk::Action::create ("Dir", _("_Directory"))); grpAction->add (apMenus[START] = Gtk::Action::create ("Start", _("_Start compare")), Gtk::AccelKey (_("s")), mem_fun (*this, &XDirComp::startCompare)); grpAction->add (apMenus[STOP] = Gtk::Action::create ("EndComp", Gtk::Stock::CLOSE, _("S_top compare")), Gtk::AccelKey (_("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 (_("N")), bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_NONEWDEL)); grpAction->add (Gtk::ToggleAction::create ("ShowChg", _("Show _changed files"), "", true), Gtk::AccelKey (_("N")), bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_NOCHANGED)); grpAction->add (Gtk::ToggleAction::create ("ShowEqual", _("Show _equal files")), Gtk::AccelKey (_("E")), bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_EQUAL)); grpAction->add (Gtk::ToggleAction::create ("ShowChgDirs", _("Show _changed dirs")), Gtk::AccelKey (_("D")), bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_NODIRCOMP)); grpAction->add (Gtk::ToggleAction::create ("ShowHidden", _("Show _hidden files")), Gtk::AccelKey (_("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 (_("S")), mem_fun (*this, &XDirComp::searchSubdirs)); grpAction->add (apMenus[EQUALSUBDIRS] = Gtk::ToggleAction::create ("SrchEqualDirs", _("Search _equal subdirs")), Gtk::AccelKey (_("Q")), mem_fun (*this, &XDirComp::searchEqualSubdirs)); grpAction->add (apMenus[COMPARE] = Gtk::ToggleAction::create ("Comp", Gtk::Stock::FIND, _("Compare c_ontents")), Gtk::AccelKey (_("C")), bind (mem_fun (*this, &XDirComp::toggleOption), CompareDirs::OPT_CHECKCONTENTS)); grpAction->add (Gtk::ToggleAction::create ("CompAll", _("Compare _always")), Gtk::AccelKey (_("C")), mem_fun (*this, &XDirComp::compareAlways)); grpAction->add (Gtk::Action::create ("SelFiles", _("Select _files ...")), Gtk::AccelKey (_("F")), mem_fun (*this, &XDirComp::selectFiles)); grpAction->add (Gtk::Action::create ("SelDirs", _("Select d_irectories ...")), Gtk::AccelKey (_("F")), mem_fun (*this, &XDirComp::selectDirectories)); grpAction->add (Gtk::Action::create ("StartDate", _("_Lower date-border ...")), Gtk::AccelKey (_("T")), bind (mem_fun (*this, &XDirComp::selectDate), false)); grpAction->add (Gtk::Action::create ("EndDate", _("_Upper date-border ...")), Gtk::AccelKey (_("T")), bind (mem_fun (*this, &XDirComp::selectDate), true)); addHelpMenu (ui); 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::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::create (this, (YGP::OThread::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::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::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::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; }