// This is an example not a library
/***************************************************************************
 *   Copyright (C) 2009 Radek Novacek    <rnovacek@redhat.com>             *
 *   Copyright (C) 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>        *
 *                                                                         *
 *   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.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
 ***************************************************************************/

#include "PkExample.h"

#include "gui/polkit-tqt-gui-actionbutton.h"
#include "gui/polkit-tqt-gui-actionbuttons.h"
#include "core/polkit-tqt-authority.h"

#include <tqdbusconnection.h>
#include <tqdbuserror.h>
#include <tqdbusmessage.h>
#include <tqdbusproxy.h>

#include <tqvariant.h>
#include <tqlabel.h>
#include <tqpushbutton.h>
#include <tqcombobox.h>
#include <tqheader.h>
#include <tqlistview.h>
#include <tqlayout.h>
#include <tqtooltip.h>
#include <tqwhatsthis.h>
#include <tqaction.h>
#include <tqmenubar.h>
#include <tqpopupmenu.h>
#include <tqtoolbar.h>

using namespace PolkitTQt;
using namespace PolkitTQt::Gui;


PkExample::PkExample() : TQMainWindow(nullptr, "Polkit tqt example application", WDestructiveClose)
{
  TQWidget *privateLayoutWidget = new TQWidget(this, "qt_central_widget");
  setCentralWidget(privateLayoutWidget);

  grid = new TQGridLayout(nullptr, 9, 1, 0, 6, "grid");
  grid->setColSpacing(0, 700);
  grid->setColSpacing(1, 200);

  kickL = new TQLabel(privateLayoutWidget, "kickL");
  kickPB = new TQPushButton(privateLayoutWidget, "kickPB");
  grid->addWidget(kickL, 0, 0);
  grid->addWidget(kickPB, 0, 1);

  cryL = new TQLabel(privateLayoutWidget, "cryL");
  cryPB = new TQPushButton(privateLayoutWidget, "cryPB");
  grid->addWidget(cryL, 1, 0);
  grid->addWidget(cryPB, 1, 1);

  bleedL = new TQLabel(privateLayoutWidget, "bleedL");
  bleedPB = new TQPushButton(privateLayoutWidget, "bleedPB");
  grid->addWidget(bleedL, 2, 0);
  grid->addWidget(bleedPB, 2, 1);

  playL = new TQLabel(privateLayoutWidget, "playL");
  playPB = new TQPushButton(privateLayoutWidget, "playPB");
  grid->addWidget(playL, 3, 0);
  grid->addWidget(playPB, 3, 1);

  listenL = new TQLabel(privateLayoutWidget, "listenL");
  listenPB = new TQPushButton(privateLayoutWidget, "listenPB");
  grid->addWidget(listenL, 4, 0);
  grid->addWidget(listenPB, 4, 1);

  deleteL = new TQLabel(privateLayoutWidget, "deleteL");
  deletePB = new TQPushButton(privateLayoutWidget, "deletePB");
  grid->addWidget(deleteL, 5, 0);
  grid->addWidget(deletePB, 5, 1);

  deleteL_2 = new TQLabel(privateLayoutWidget, "deleteL_2");
  setCB = new TQComboBox(false, privateLayoutWidget, "setCB");
  grid->addMultiCellWidget(deleteL_2, 6, 7, 0, 0);
  grid->addWidget(setCB, 6, 1);

  setPB = new TQPushButton(privateLayoutWidget, "setPB");
  deleteL_3 = new TQLabel(privateLayoutWidget, "deleteL_3");
  grid->addWidget(setPB, 7, 1);
  grid->addWidget(deleteL_3, 8, 0);

  shoutPB = new TQPushButton(privateLayoutWidget, "shoutPB");
  grid->addWidget(shoutPB, 8, 1);

  vLayout = new TQVBoxLayout(privateLayoutWidget, 11, 6, "vLayout");
  vLayout->addLayout(grid);

  actionList = new TQListView(privateLayoutWidget);
  actionList->addColumn("Action");
  actionList->addColumn("Result");
  actionList->setSorting(-1);

  vLayout->addWidget(actionList);

  // menubar
  menubar = new TQMenuBar(this, "menubar");
  menubar->setGeometry(TQRect(0, 0, 800, 22));
  menuActions = new TQPopupMenu(this);
  menubar->insertItem(TQString(""), menuActions, 2);

  // toolbars
  toolBar = new TQToolBar(TQString(""), this, DockTop);

  // statusbar
  statusBar();

  languageChange();
  resize(TQSize(900, 700).expandedTo(minimumSizeHint()));
  clearWState(WState_Polished);

  // Setup actions
  ActionButton *bt;

  // Here we create an ActionButton that is a subclass of Action
  // always pass a TQButton pointer and action id
  // You can change the action id later if you want
  bt = new ActionButton(kickPB, "org.tqt.policykit.examples.kick", this);
  // Here we are setting the text and icon to all four states
  // an action might have
  bt->setText("Kick!");
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"));
  // By using set{Yes|No|Auth}Enabled you can set the states
  // when the button is enabled
  bt->setEnabled(true, Action::No);
  // As ActionButton is also an Action we cast it to add to menu
  ::tqt_cast<TQAction*>(bt)->addTo(menuActions);
  ::tqt_cast<TQAction*>(bt)->addTo(toolBar);
  // this signal is emitted when the user click on the action,
  // it will only happen if it was inserted in a TQMenu or a TQToolBar
  connect(bt, TQ_SIGNAL(activated()), this, TQ_SLOT(activateAction()));
  // This signal was propagated from the TQButton just for
  // convenience in this case we don't have any benefit but the code
  // look cleaner
  connect(bt, TQ_SIGNAL(clicked(TQButton*, bool)), bt, TQ_SLOT(activate()));
  // this is the Action activated signal, it is always emmited whenever
  // someone click and get authorized to do the action
  connect(bt, TQ_SIGNAL(authorized()), this, TQ_SLOT(actionActivated()));

  bt = new ActionButton(cryPB, "org.tqt.policykit.examples.cry", this);
  bt->setText("Cry!");
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"));
  ::tqt_cast<TQAction*>(bt)->addTo(menuActions);
  ::tqt_cast<TQAction*>(bt)->addTo(toolBar);
  connect(bt, TQ_SIGNAL(activated()), this, TQ_SLOT(activateAction()));
  connect(bt, TQ_SIGNAL(clicked(TQButton*, bool)), bt, TQ_SLOT(activate()));
  connect(bt, TQ_SIGNAL(authorized()), this, TQ_SLOT(actionActivated()));

  bt = new ActionButton(bleedPB, "org.tqt.policykit.examples.bleed", this);
  bt->setText("Bleed!");
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"));
  ::tqt_cast<TQAction*>(bt)->addTo(menuActions);
  ::tqt_cast<TQAction*>(bt)->addTo(toolBar);
  connect(bt, TQ_SIGNAL(activated()), this, TQ_SLOT(activateAction()));
  connect(bt, TQ_SIGNAL(clicked(TQButton*, bool)), bt, TQ_SLOT(activate()));
  connect(bt, TQ_SIGNAL(authorized()), this, TQ_SLOT(actionActivated()));

  // This action is more customized
  bt = new ActionButton(playPB, "org.tqt.policykit.examples.play", this);
  bt->setText("Play!");
  bt->setVisible(true, (Action::States)(Action::No | Action::Auth | Action::Yes));
  bt->setEnabled(true, (Action::States)(Action::No | Action::Auth | Action::Yes));
  // here we set the behavior of PolKitResult = No
  bt->setText("Can't play!", Action::No);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No);
  bt->setToolTip("If your admin wasn't annoying, you could do this", Action::No);
  // here we set the behavior of PolKitResult = Auth
  bt->setText("Play?", Action::Auth);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth);
  bt->setToolTip("Only card carrying tweakers can do this!", Action::Auth);
  // here we set the behavior of PolKitResult = Yes
  bt->setText("Play!", Action::Yes);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes);
  bt->setToolTip("Go ahead, play!", Action::Yes);
  ::tqt_cast<TQAction*>(bt)->addTo(menuActions);
  ::tqt_cast<TQAction*>(bt)->addTo(toolBar);
  connect(bt, TQ_SIGNAL(activated()), this, TQ_SLOT(activateAction()));
  connect(bt, TQ_SIGNAL(clicked(TQButton*, bool)), bt, TQ_SLOT(activate()));
  connect(bt, TQ_SIGNAL(authorized()), this, TQ_SLOT(actionActivated()));

  bt = new ActionButton(listenPB, "org.tqt.policykit.examples.listen", this);
  bt->setText("Listen!");
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes);
  ::tqt_cast<TQAction*>(bt)->addTo(menuActions);
  ::tqt_cast<TQAction*>(bt)->addTo(toolBar);
  connect(bt, TQ_SIGNAL(activated()), this, TQ_SLOT(activateAction()));
  connect(bt, TQ_SIGNAL(clicked(TQButton*, bool)), bt, TQ_SLOT(activate()));
  connect(bt, TQ_SIGNAL(authorized()), this, TQ_SLOT(actionActivated()));

  bt = new ActionButton(deletePB, "org.tqt.policykit.examples.delete", this);
  bt->setText("Delete!");
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes);
  ::tqt_cast<TQAction*>(bt)->addTo(menuActions);
  ::tqt_cast<TQAction*>(bt)->addTo(toolBar);
  connect(bt, TQ_SIGNAL(activated()), this, TQ_SLOT(activateAction()));
  connect(bt, TQ_SIGNAL(clicked(TQButton*, bool)), bt, TQ_SLOT(activate()));
  connect(bt, TQ_SIGNAL(authorized()), this, TQ_SLOT(actionActivated()));

  bt = new ActionButton(setPB, "org.tqt.policykit.examples.set", this);
  bt->setText("Set!");
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes);
  ::tqt_cast<TQAction*>(bt)->addTo(menuActions);
  ::tqt_cast<TQAction*>(bt)->addTo(toolBar);
  connect(bt, TQ_SIGNAL(activated()), this, TQ_SLOT(activateAction()));
  connect(bt, TQ_SIGNAL(clicked(TQButton*, bool)), bt, TQ_SLOT(activate()));
  connect(bt, TQ_SIGNAL(authorized()), this, TQ_SLOT(actionActivated()));

  bt = new ActionButton(shoutPB, "org.tqt.policykit.examples.shout", this);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth);
  bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes);
  bt->setText("Can't shout!", Action::No);
  bt->setText("Shout?", Action::Auth);
  bt->setText("Shout!", Action::Yes);
  ::tqt_cast<TQAction*>(bt)->addTo(menuActions);
  ::tqt_cast<TQAction*>(bt)->addTo(toolBar);
  connect(bt, TQ_SIGNAL(activated()), this, TQ_SLOT(activateAction()));
  connect(bt, TQ_SIGNAL(clicked(TQButton*, bool)), bt, TQ_SLOT(activate()));
  connect(bt, TQ_SIGNAL(authorized()), this, TQ_SLOT(actionActivated()));
}

void PkExample::languageChange()
{
  setCaption(tr("PolicyKit-tqt example"));
  kickL->setText(tr("Making the helper <b>Kick</b> is not allowed. Action cannot be activated."));
  kickPB->setText(tr("Kick!"));
  cryL->setText(tr("Making the helper <b>Cry</b> is always allowed. Action can be activated without authentication."));
  cryPB->setText(tr("Cry!"));
  bleedL->setText(tr("Making the helper <b>Bleed</b> requires the user to authenticate. This is a one-shot authorization."));
  bleedPB->setText(tr("Bleed!"));
  playL->setText(tr("Making the helper <b>Play</b> requires a system administrator to authenticate. This is a one-shot authorization."));
  playPB->setText(tr("Play!"));
  listenL->setText(tr("Making the helper <b>Listen</b> requires the user to authenticate. The authorization will be kept for a brief period."));
  listenPB->setText(tr("Listen!"));
  deleteL->setText(tr("Making the helper <b>Delete</b> requires a system administrator to authenticate. The authorization will be kept for a brief period."));
  deletePB->setText(tr("Delete!"));
  deleteL_2->setText(tr("<b>Set</b> is special action. It sets the permissions for the <b>Shout</b> action by actually using the helper application to change the implicit authorization."));
  setCB->clear();
  setCB->insertItem(tr("no"));
  setCB->insertItem(tr("yes"));
  setCB->insertItem(tr("auth_self"));
  setCB->insertItem(tr("auth_admin"));
  setCB->insertItem(tr("auth_self_keep"));
  setCB->insertItem(tr("auth_admin_keep"));
  setPB->setText(tr("Set!"));
  deleteL_3->setText(tr("The implicit authorization for the <b>Shout</b> action is set by the <b>Set</b> action. You can watch how different options can change behaviour of this action."));
  shoutPB->setText(tr("Shout!"));
  toolBar->setCaption(tr("toolBar"));
  if (menubar->findItem(2))
  {
    menubar->findItem(2)->setText(tr("&Actions"));
  }
}

void PkExample::activateAction()
{
  // Here we cast the sender() to an Action and call activate() on it.
  // Be careful in doing the same for ActionButton won't work as expected
  // as action->activate() is calling Action::activate() and
  // not ActionButton::activate which are different.
  // You can cast then to ActionButton but be carefull
  // an Action casted to ActionButton may crash you app
  Action *action = ::tqt_cast<Action*>(sender());
  // calling activate with winId() makes the auth dialog
  // be correct parented with your application.
  action->activate();
}

void PkExample::actionActivated()
{
  // This slot is called whenever an action is allowed
  // here you will do your dirt job by calling a helper application
  // that might erase your hardrive ;)
  Action *action = ::tqt_cast<Action*>(sender());

  // this is our Special Action that after allowed will call the helper
  if (action->is("org.tqt.policykit.examples.set"))
  {
    tqDebug("toggled for: org.tqt.policykit.examples.set");

    TQT_DBusConnection dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus);
    TQT_DBusProxy exampleProxy("org.tqt.policykit.examples", "/", "org.tqt.policykit.examples", dbusConn);
    TQT_DBusError error;
    TQValueList<TQT_DBusData> params;
    params << TQT_DBusData::fromString(setCB->currentText());
    TQT_DBusMessage reply = exampleProxy.sendWithReply("set", params, &error);
    if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1)
    {
      // the reply can be anything, here we receive a bool
      TQListViewItem *item;
      if (reply[0].toBool())
      {
        item = new TQListViewItem(actionList);
        item->setText(0, TQString("Implicit authorization for shout has been set to ") +
                setCB->currentText());
        item->setPixmap(1, TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"));
      }
      else
      {
        item = new TQListViewItem(actionList);
        item->setText(0, TQString("Can't change the implicit authorization. Denied."));
        item->setPixmap(1, TQPixmap("/usr/share/apps/icons/custom-no.png"));
      }
      actionList->insertItem(item);
    }
    else if (reply.type() == TQT_DBusMessage::MethodCallMessage)
    {
      tqDebug("Message did not receive a reply (timeout by message bus)");
    }
    return;
  }

  // As debug message says we are pretending to be the mechanism for the
  // following action, here you will actually call your DBus helper that
  // will run as root (setuid is not needed, see DBus docs).
  // In the helper application you will issue checkAuthorizationSync,
  // passing the action id and the caller pid (which DBus will tell you).
  tqDebug(TQString("Pretending to be the mechanism for action %1").arg(action->actionId()));

  Authority::Result result;
  UnixProcessSubject subject(static_cast<uint>(getpid()));
  result = Authority::instance()->checkAuthorizationSync(action->actionId(), subject,
      Authority::AllowUserInteraction);
  TQListViewItem *item;
  item = new TQListViewItem(actionList);
  item->setText(0, action->actionId());
  if (result == Authority::Yes)
  {
    // in the helper you will do the action
    tqDebug(TQString("caller is authorized to do: %1").arg(action->actionId()));
    item->setPixmap(1, TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"));
  }
  else
  {
    // or return false to notify the caller that the action is not authorized.
    tqDebug(TQString("caller is NOT authorized to do: %1").arg(action->actionId()));
    item->setPixmap(1, TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"));
  }
  actionList->insertItem(item);
}

#include "PkExample.moc"
