Logo Search packages:      
Sourcecode: paco version File versions  Download package

removetab.cc

//=======================================================================
// removetab.cc
//-----------------------------------------------------------------------
// This file is part of the package paco
// Copyright (C) 2004-2009 David Rosal
// For more information visit http://paco.sourceforge.net
//=======================================================================

#include "config.h"
#include "gconfig.h"
#include "util.h"
#include "removetab.h"
#include "paco/file.h"
#include "pkgwindow.h"
#include "mainwindow.h"
#include "maintreeview.h"
#include <gtkmm/stock.h>
#include <gtkmm/table.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/sizegroup.h>
#include <gtkmm/separator.h>

#define RETURN_IF_NO_WINDOW  if (!mPkg.window()) return;


using Glib::ustring;
using std::string;
using sigc::mem_fun;
using namespace Gpaco;


RemoveTab::RemoveTab(Pkg& pkg)
:
      Gtk::VBox(),
      mPkg(pkg),
      mPkgSet(gpMainWindow->treeView()->pkgSet()),
      mLabel("", 0.02, 0.5),
      mRemoveShared(false),
      mButtonShared("Remove _shared", true),
      mButtonRemove(Gtk::Stock::DELETE, "_Remove"),
      mButtonStop(Gtk::Stock::STOP, "_Stop"),
      mButtonResume(Gtk::Stock::DELETE, "_Resume"),
      mTextView(),
      mpTextBuffer(mTextView.get_buffer()),
      mpTagSuccess(mpTextBuffer->create_tag()),
      mpTagError(mpTextBuffer->create_tag()),
      mpTagShared(mpTextBuffer->create_tag()),
      mStop(false)
{
      mButtonShared.signal_clicked().connect(mem_fun(*this, &RemoveTab::onSwitchRemoveShared));
      mButtonShared.set_sensitive(GConfig::logdirWritable());
      mButtonShared.set_tooltip_text("Remove the shared files (those files "
            "which are also owned by other packages)");

      mButtonRemove.signal_clicked().connect(mem_fun(*this, &RemoveTab::onRemove));
      mButtonRemove.set_sensitive(GConfig::logdirWritable());

      mButtonStop.signal_clicked().connect(mem_fun(*this, &RemoveTab::onStop));
      mButtonResume.signal_clicked().connect(mem_fun(*this, &RemoveTab::onResume));

      Gtk::Table* pTable(Gtk::manage(new Gtk::Table(1, 1)));
      pTable->attach(mButtonRemove, 0, 1, 0, 1);
      pTable->attach(mButtonStop, 0, 1, 0, 1);
      pTable->attach(mButtonResume, 0, 1, 0, 1);

      Glib::RefPtr<Gtk::SizeGroup> pSizeGroup(Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL));
      pSizeGroup->add_widget(mButtonRemove);
      pSizeGroup->add_widget(mButtonStop);
      pSizeGroup->add_widget(mButtonResume);

      Gtk::ScrolledWindow* pScrolledWindow(Gtk::manage(new Gtk::ScrolledWindow()));
      pScrolledWindow->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
      pScrolledWindow->add(mTextView);

      mTextView.set_editable(false);
      mTextView.set_cursor_visible(false);
      mTextView.set_left_margin(4);
      mTextView.set_right_margin(4);
      mTextView.modify_base(Gtk::STATE_NORMAL, Gdk::Color("black"));

      mpTagSuccess->property_foreground() = "white";
      mpTagSuccess->property_weight() = Pango::WEIGHT_BOLD;
      mpTagSuccess->property_family() = "courier";
      mpTagError->property_foreground() = "red";
      mpTagError->property_weight() = Pango::WEIGHT_BOLD;
      mpTagError->property_family() = "courier";
      mpTagShared->property_foreground() = "lightgreen";
      mpTagShared->property_weight() = Pango::WEIGHT_BOLD;
      mpTagShared->property_family() = "courier";

      Gtk::HBox* pHBox(Gtk::manage(new Gtk::HBox()));
      pHBox->set_border_width(2);
      pHBox->pack_start(mButtonShared, Gtk::PACK_SHRINK);
      pHBox->pack_end(*pTable, Gtk::PACK_SHRINK);

      pack_start(*pHBox, Gtk::PACK_SHRINK);
      pack_start(*pScrolledWindow);
      pack_start(*(Gtk::manage(new Gtk::HSeparator())), Gtk::PACK_SHRINK);
      pack_start(mLabel, Gtk::PACK_SHRINK);

      show_all();
}


RemoveTab::~RemoveTab()
{ }



//---------//
// private //
//---------//


void RemoveTab::report(std::string const& path, int code)
{
      Glib::RefPtr<Gtk::TextTag>* tag = &mpTagSuccess;
      ustring msg;
      
      switch (code) {
            case REPORT_REGULAR:
                  msg = "Removed " + path;
                  break;
            case REPORT_SYMLINK:
                  msg = "Removed symlink " + path;
                  break;
            case REPORT_DIR:
                  msg = "Removed directory " + path;
                  break;
            case REPORT_ERROR:
                  tag = &mpTagError;
                  msg = "ERROR: " + path + ": " + Glib::strerror(errno);
                  break;
            case REPORT_SHARED:
                  tag = &mpTagShared;
                  msg = path + ": shared";
                  break;
            case REPORT_UNLOG:
                  msg = "\nPackage " + mPkg.name() + " removed from database";
                  break;
            default:
                  g_assert_not_reached();
      }

      RETURN_IF_NO_WINDOW;
      mpTextBuffer->insert_with_tag(mpTextBuffer->end(), msg + "\n", *tag);
      Gtk::TextIter end = mpTextBuffer->end();
      mTextView.scroll_to(end);
      refreshMainLoop();
}


bool RemoveTab::removeFile(File* file)
{
      g_assert(file != NULL);

      struct stat s;
      bool ret = false;

      if (!lstat(file->name().c_str(), &s)) {
            if (!mRemoveShared && mPkg.shares(file, mPkgSet))
                  report(file->name(), REPORT_SHARED);
            else if (!unlink(file->name().c_str())) {
                  report(file->name(), S_ISLNK(s.st_mode) ? REPORT_SYMLINK : REPORT_REGULAR);
                  ret = true;
            }
            else
                  report(file->name(), REPORT_ERROR);
      }

      return ret;
}


void RemoveTab::removeDir(string const& dir)
{
      if (dir.find("/", 1) == string::npos)
            return;
      else if (!rmdir(dir.c_str())) {
            report(dir, REPORT_DIR);
            removeDir(Glib::path_get_dirname(dir));
      }
      else if (errno != ENOTDIR && errno != ENOENT && errno != ENOTEMPTY)
            report(dir, REPORT_ERROR);
}


void RemoveTab::onRemove()
{
      g_assert(GConfig::logdirWritable());
      g_assert(mStop == false);

      if (!questionDialog(mPkg.window(), "Remove the package " + mPkg.name() + " ?"))
            return;
      
      mpTextBuffer->erase(mpTextBuffer->begin(), mpTextBuffer->end());
      mpTextBuffer->insert(mpTextBuffer->end(), "\n");

      mButtonRemove.hide();
      mButtonStop.show();

      long files = 0, size = 0;

____loop:
      for (Pkg::iterator f = mPkg.begin(); f != mPkg.end(); ++f) {

            if (mStop && mPkg.window()) {
                  while (mStop && mPkg.window()) {
                        Glib::usleep(3000);
                        refreshMainLoop();
                  }
                  goto ____loop;
            }

            if (removeFile(*f)) {
                  ++files; 
                  size += (*f)->size();
                  std::ostringstream txt;
                  txt << "Removed " << files << " file" << (files > 1 ? "s" : "");
                  if (size > 0)
                        txt << "  (" << Paco::toString(size) << ")";
                  RETURN_IF_NO_WINDOW;
                  mLabel.set_text(txt.str());
                  removeDir(Glib::path_get_dirname((*f)->name()));
            }
      }

      if (!mPkg.update())
            report("", REPORT_UNLOG);
      else if (!mPkg.filesInst()) { // all files removed
            if (!unlink(mPkg.log().c_str()))
                  report("", REPORT_UNLOG);
            else
                  report(mPkg.log(), REPORT_ERROR);
      }
      
      RETURN_IF_NO_WINDOW;
      mButtonStop.hide();
      mButtonRemove.show();
      mButtonRemove.set_sensitive(false);
}


void RemoveTab::onStop()
{
      g_assert(mStop == false);
      mStop = true;
      mPkg.update();
      mButtonStop.hide();
      mButtonResume.show();
}


void RemoveTab::onResume()
{
      g_assert(mStop == true);
      mStop = false;
      mButtonStop.show();
      mButtonResume.hide();
}


void RemoveTab::onSwitchRemoveShared()
{
      mRemoveShared = !mRemoveShared;
}


Generated by  Doxygen 1.6.0   Back to index