[kde-doc-english] [k3b] /: Moved K3bSetup functionality to K3b's config dialog

Michal Malek michalm at jabster.pl
Sun Sep 11 20:11:04 UTC 2011


Git commit 127d389fe61c77225eb8efab0c53ddf2ef704fdf by Michal Malek.
Committed on 11/09/2011 at 17:56.
Pushed by mmalek into branch 'master'.

Moved K3bSetup functionality to K3b's config dialog

K3bSetup never really belonged to SystemSettings. When user wanted
to change device or programs permissions he'd needed to switch to
SystemSettings which was not obvious. Hence this settings were moved
to K3b settings window. Program permissions can now be changed in a new
"Permissions" tab on "Programs" section.
Modification of devices permissions has been removed altogether. In
all (?) modern systems optical devices belongs to a certain user group
(e.g. "cdrom"). If the current user does not belongs to this group,
he's offered to add himself to it in "Devices" section of K3b settings
window.

FEATURE: 220040
FIXED-IN: 2.1.0
GUI: K3bSetup no longer exists

M  +0    -8    CMakeLists.txt
M  +1    -0    ChangeLog
M  +0    -1    config-k3b.h.cmake
D  +0    -1    k3bsetup/.krazy
D  +0    -34   k3bsetup/CMakeLists.txt
D  +0    -5    k3bsetup/Messages.sh
D  +0    -256  k3bsetup/base_k3bsetup.ui
D  +0    -18   k3bsetup/k3bsetup
D  +0    -282  k3bsetup/k3bsetup.cpp
D  +0    -212  k3bsetup/k3bsetup.desktop
D  +0    -49   k3bsetup/k3bsetup.h
D  +0    -320  k3bsetup/k3bsetupdevicesmodel.cpp
D  +0    -72   k3bsetup/k3bsetupdevicesmodel.h
D  +0    -74   k3bsetup/k3bsetupprogramsmodel.h
M  +1    -3    libk3b/projects/k3bcdrecordwriter.cpp
M  +10   -1    src/CMakeLists.txt
A  +10   -0    src/helper/CMakeLists.txt
R  +6    -1    src/helper/k3b.actions [from: k3bsetup/k3bsetup.actions - 097% similarity]
R  +41   -23   src/helper/k3bhelper.cpp [from: k3bsetup/k3bsetupworker.cpp - 066% similarity]
R  +15   -11   src/helper/k3bhelper.h [from: k3bsetup/k3bsetupworker.h - 065% similarity]
R  +6    -8    src/helper/k3bhelperprogramitem.cpp [from: k3bsetup/k3bsetupprogramitem.cpp - 064% similarity]
R  +13   -15   src/helper/k3bhelperprogramitem.h [from: k3bsetup/k3bsetupprogramitem.h - 051% similarity]
M  +0    -18   src/k3b.cpp
M  +0    -1    src/k3b.h
M  +34   -39   src/k3bsystemproblemdialog.cpp
M  +4    -2    src/k3bsystemproblemdialog.h
M  +0    -1    src/k3bui.rc
M  +7    -33   src/option/k3bdeviceoptiontab.cpp
M  +1    -4    src/option/k3bdeviceoptiontab.h
M  +78   -26   src/option/k3bdevicewidget.cpp
M  +7    -1    src/option/k3bdevicewidget.h
R  +65   -95   src/option/k3bexternalbinpermissionmodel.cpp [from: k3bsetup/k3bsetupprogramsmodel.cpp - 068% similarity]
A  +75   -0    src/option/k3bexternalbinpermissionmodel.h     [License: GPL (v2+)]
M  +96   -6    src/option/k3bexternalbinwidget.cpp
M  +7    -1    src/option/k3bexternalbinwidget.h
M  +1    -1    src/option/k3boptiondialog.cpp

http://commits.kde.org/k3b/127d389fe61c77225eb8efab0c53ddf2ef704fdf

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 266d599..d2e50b0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,7 +25,6 @@ option(K3B_ENABLE_DVD_RIPPING "Support for ripping Video DVDs with optional decr
 option(K3B_ENABLE_TAGLIB "Support for reading audio file metadata using Taglib." ON)
 option(K3B_BUILD_API_DOCS "Build the API documentation for the K3b libs." OFF)
 if(NOT WIN32 AND NOT APPLE)
-  option(K3B_BUILD_K3BSETUP "Graphical utility for managing device permissions" ON)
   option(K3B_ENABLE_HAL_SUPPORT "Support for inhibiting HAL from polling disk during write." OFF)
 endif(NOT WIN32 AND NOT APPLE)
 
@@ -164,10 +163,6 @@ endif(WIN32)
 ##################  K3b build settings #################################
 include(ConfigureChecks)
 
-if(K3B_BUILD_K3BSETUP)
-  set(BUILD_K3BSETUP 1)
-endif(K3B_BUILD_K3BSETUP)
-
 macro_bool_to_01(ADD_K3B_DEBUG K3B_DEBUG)
 
 if(K3B_ENABLE_DVD_RIPPING AND DVDREAD_FOUND)
@@ -288,9 +283,6 @@ add_subdirectory( src )
 add_subdirectory( kioslaves )
 add_subdirectory( plugins )
 add_subdirectory( doc )
-if(BUILD_K3BSETUP)
-    add_subdirectory(k3bsetup)
-endif(BUILD_K3BSETUP)
 if(KDE4_BUILD_TESTS)
     enable_testing()
     add_subdirectory( tests )
diff --git a/ChangeLog b/ChangeLog
index 8548196..496b7b1c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@ Changes:
  * Revamped project size indicator widget - it now fits better into a widget style
  * Using KDE Plasma's global progress bar replacing K3b's own progress OSD (205843)
  * Usability: reduced number of message boxes interrupting user actions (196604)
+ * Moved configuration of devices and programs permissions from SystemSettings to K3b's own settings window (220040)
 
 Bugfixes:
  * Added dynamic hiding of irrelevant actions in mixed project (142954)
diff --git a/config-k3b.h.cmake b/config-k3b.h.cmake
index 5149e6b..50c4a99 100644
--- a/config-k3b.h.cmake
+++ b/config-k3b.h.cmake
@@ -1,5 +1,4 @@
 /* config-k3b.h. Generated by cmake from config-k3b.h.cmake */
-#cmakedefine BUILD_K3BSETUP
 
 #cmakedefine K3B_DEBUG
 
diff --git a/k3bsetup/.krazy b/k3bsetup/.krazy
deleted file mode 100644
index bbcb2df..0000000
--- a/k3bsetup/.krazy
+++ /dev/null
@@ -1 +0,0 @@
-EXCLUDE dpointer,inline,sigsandslots
diff --git a/k3bsetup/CMakeLists.txt b/k3bsetup/CMakeLists.txt
deleted file mode 100644
index 076bcc9..0000000
--- a/k3bsetup/CMakeLists.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-########### next target ###############
-
-include_directories(
-    ../libk3b/core/
-)
-
-set(kcm_k3bsetup_PART_SRCS
-    k3bsetup.cpp
-    k3bsetupdevicesmodel.cpp
-    k3bsetupprogramitem.cpp
-    k3bsetupprogramsmodel.cpp )
-
-kde4_add_ui_files(kcm_k3bsetup_PART_SRCS base_k3bsetup.ui )
-
-kde4_add_plugin(kcm_k3bsetup ${kcm_k3bsetup_PART_SRCS})
-
-target_link_libraries(kcm_k3bsetup ${KDE4_KDEUI_LIBS} k3b k3bdevice )
-
-install(TARGETS kcm_k3bsetup DESTINATION ${PLUGIN_INSTALL_DIR} )
-
-
-########### install files ###############
-install( PROGRAMS  k3bsetup DESTINATION ${BIN_INSTALL_DIR} )
-install( FILES  k3bsetup.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
-
-
-########### next target ###############
-kde4_add_executable(k3bsetuphelper k3bsetupworker.cpp k3bsetupprogramitem.cpp)
-target_link_libraries(k3bsetuphelper ${KDE4_KDECORE_LIBRARY})
-install(TARGETS k3bsetuphelper DESTINATION ${LIBEXEC_INSTALL_DIR})
-
-kde4_install_auth_helper_files(k3bsetuphelper org.kde.kcontrol.k3bsetup root)
-
-kde4_install_auth_actions(org.kde.kcontrol.k3bsetup k3bsetup.actions)
diff --git a/k3bsetup/Messages.sh b/k3bsetup/Messages.sh
deleted file mode 100644
index 70b05d4..0000000
--- a/k3bsetup/Messages.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#! /bin/sh
-$EXTRACTRC *.ui >> rc.cpp
-$XGETTEXT *.cpp -o $podir/k3bsetup.pot
-
-
diff --git a/k3bsetup/base_k3bsetup.ui b/k3bsetup/base_k3bsetup.ui
deleted file mode 100644
index c333d0c..0000000
--- a/k3bsetup/base_k3bsetup.ui
+++ /dev/null
@@ -1,256 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>base_K3bSetup</class>
- <widget class="QWidget" name="base_K3bSetup">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>634</width>
-    <height>600</height>
-   </rect>
-  </property>
-  <layout class="QHBoxLayout">
-   <property name="margin">
-    <number>0</number>
-   </property>
-   <item>
-    <layout class="QVBoxLayout">
-     <item>
-      <widget class="QGroupBox" name="groupBox3">
-       <property name="title">
-        <string>Settings</string>
-       </property>
-       <layout class="QVBoxLayout">
-        <item>
-         <layout class="QHBoxLayout">
-          <item>
-           <widget class="QCheckBox" name="m_checkUseBurningGroup">
-            <property name="whatsThis">
-             <string><p>If this option is checked, only the users in the specified group will be able to burn CDs and DVDs, since only they will have access to the devices and the CD recording programs used by K3b.</p>
-<p>Otherwise all users on the system have access to the devices and to all K3b functionality.</string>
-            </property>
-            <property name="text">
-             <string>Use burning group:</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="KLineEdit" name="m_editBurningGroup">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-            <property name="text">
-             <string>burning</string>
-            </property>
-            <property name="showClearButton" stdset="0">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </item>
-        <item>
-         <widget class="QFrame" name="m_frameUsers">
-          <layout class="QHBoxLayout" name="horizontalLayout">
-           <property name="margin">
-            <number>0</number>
-           </property>
-           <item>
-            <spacer name="spacer1">
-             <property name="orientation">
-              <enum>Qt::Horizontal</enum>
-             </property>
-             <property name="sizeType">
-              <enum>QSizePolicy::Fixed</enum>
-             </property>
-             <property name="sizeHint" stdset="0">
-              <size>
-               <width>20</width>
-               <height>10</height>
-              </size>
-             </property>
-            </spacer>
-           </item>
-           <item>
-            <widget class="QLabel" name="textLabel2">
-             <property name="text">
-              <string>Users allowed to burn (separated by space):</string>
-             </property>
-             <property name="wordWrap">
-              <bool>false</bool>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <widget class="KLineEdit" name="m_editUsers">
-             <property name="enabled">
-              <bool>false</bool>
-             </property>
-             <property name="showClearButton" stdset="0">
-              <bool>true</bool>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </widget>
-        </item>
-       </layout>
-      </widget>
-     </item>
-     <item>
-      <widget class="QGroupBox" name="groupBox1">
-       <property name="title">
-        <string>Devices</string>
-       </property>
-       <layout class="QVBoxLayout">
-        <item>
-         <widget class="QLabel" name="textLabel1_2">
-          <property name="text">
-           <string>Check the devices whose permissions you want to be changed</string>
-          </property>
-          <property name="wordWrap">
-           <bool>false</bool>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QTreeView" name="m_viewDevices">
-          <property name="rootIsDecorated">
-           <bool>false</bool>
-          </property>
-          <attribute name="headerStretchLastSection">
-           <bool>false</bool>
-          </attribute>
-         </widget>
-        </item>
-       </layout>
-      </widget>
-     </item>
-     <item>
-      <widget class="QGroupBox" name="groupBox2">
-       <property name="title">
-        <string>External Programs</string>
-       </property>
-       <layout class="QVBoxLayout">
-        <item>
-         <widget class="QTabWidget" name="tabWidget2">
-          <property name="currentIndex">
-           <number>0</number>
-          </property>
-          <widget class="QWidget" name="foundProgramstab">
-           <attribute name="title">
-            <string>Found Programs</string>
-           </attribute>
-           <layout class="QVBoxLayout">
-            <item>
-             <widget class="QLabel" name="textLabel1">
-              <property name="text">
-               <string>Check the programs whose permissions you want to be changed</string>
-              </property>
-              <property name="wordWrap">
-               <bool>false</bool>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QTreeView" name="m_viewPrograms">
-              <property name="rootIsDecorated">
-               <bool>false</bool>
-              </property>
-              <attribute name="headerStretchLastSection">
-               <bool>false</bool>
-              </attribute>
-             </widget>
-            </item>
-           </layout>
-          </widget>
-          <widget class="QWidget" name="searchPathtab">
-           <attribute name="title">
-            <string>Search Path</string>
-           </attribute>
-           <layout class="QVBoxLayout">
-            <item>
-             <widget class="KEditListBox" name="m_editSearchPath">
-              <property name="title">
-               <string>Search Path</string>
-              </property>
-              <property name="flat">
-               <bool>false</bool>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="textLabel1_3">
-              <property name="text">
-               <string><qt><b>Hint:</b> to force K3b to use another than the default name for the executable specify it in the search path.</qt></string>
-              </property>
-              <property name="wordWrap">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </widget>
-         </widget>
-        </item>
-       </layout>
-      </widget>
-     </item>
-    </layout>
-   </item>
-  </layout>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <customwidgets>
-  <customwidget>
-   <class>KEditListBox</class>
-   <extends>QGroupBox</extends>
-   <header>keditlistbox.h</header>
-  </customwidget>
-  <customwidget>
-   <class>KLineEdit</class>
-   <extends>QLineEdit</extends>
-   <header>klineedit.h</header>
-  </customwidget>
- </customwidgets>
- <includes>
-  <include location="local">keditlistbox.h</include>
-  <include location="local">klineedit.h</include>
- </includes>
- <resources/>
- <connections>
-  <connection>
-   <sender>m_checkUseBurningGroup</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>m_editBurningGroup</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>121</x>
-     <y>45</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>202</x>
-     <y>43</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>m_checkUseBurningGroup</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>m_editUsers</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>55</x>
-     <y>46</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>367</x>
-     <y>80</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
-</ui>
diff --git a/k3bsetup/k3bsetup b/k3bsetup/k3bsetup
deleted file mode 100644
index fbbbeeb..0000000
--- a/k3bsetup/k3bsetup
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# $Id$
-# Copyright (C) 2003 Sebastian Trueg <trueg at k3b.org>
-#
-# This file is part of the K3b project.
-# Copyright (C) 1998-2003 Sebastian Trueg <trueg at k3b.org>
-#
-# 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.
-# See the file "COPYING" for the exact licensing terms.
-#
-
-
-#!/usr/bin/sh
-
-kcmshell4 k3bsetup
diff --git a/k3bsetup/k3bsetup.cpp b/k3bsetup/k3bsetup.cpp
deleted file mode 100644
index 0169433..0000000
--- a/k3bsetup/k3bsetup.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- *
- * Copyright (C) 2003-2009 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
- * Copyright (C) 2010 Dario Freddi <drf at kde.org>
- *
- * This file is part of the K3b project.
- * Copyright (C) 1998-2009 Sebastian Trueg <trueg at k3b.org>
- *
- * 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.
- * See the file "COPYING" for the exact licensing terms.
- */
-
-#include <config-k3b.h>
-
-#include "k3bsetup.h"
-#include "k3bsetupdevicesmodel.h"
-#include "k3bsetupprogramsmodel.h"
-#include "k3bexternalbinmanager.h"
-
-#include <QCheckBox>
-#include <QFile>
-#include <QHBoxLayout>
-#include <QHeaderView>
-#include <QLabel>
-#include <QLayout>
-#include <QLineEdit>
-#include <QMap>
-#include <QPushButton>
-#include <QTimer>
-
-#include <KAboutData>
-#include <KConfig>
-#include <KDebug>
-#include <kdeversion.h>
-#include <KEditListBox>
-#include <KGenericFactory>
-#include <KGlobal>
-#include <KLocale>
-#include <KMessageBox>
-#include <KTextEdit>
-#include <KAuth/Action>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <grp.h>
-
-
-class K3bSetup::Private
-{
-public:
-    KConfig* config;
-    K3b::Setup::DevicesModel* devicesModel;
-    K3b::Setup::ProgramsModel* programsModel;
-};
-
-
-K_PLUGIN_FACTORY(K3bSetupFactory, registerPlugin<K3bSetup>();)
-K_EXPORT_PLUGIN(K3bSetupFactory("k3bsetup"))
-
-
-
-K3bSetup::K3bSetup( QWidget *parent, const QVariantList& )
-    : KCModule( K3bSetupFactory::componentData(), parent )
-{
-    d = new Private();
-    d->config = new KConfig( "k3bsetuprc" );
-
-    qRegisterMetaType<K3b::Setup::ProgramItem>();
-    qRegisterMetaTypeStreamOperators<K3b::Setup::ProgramItem>( "K3b::Setup::ProgramItem" );
-
-    KAboutData* aboutData = new KAboutData("k3bsetup", 0,
-                                           ki18n("K3bSetup"), "2.0",
-                                           KLocalizedString(), KAboutData::License_GPL,
-                                           ki18n("(C) 2003-2007 Sebastian Trueg"), ki18n(0L));
-    aboutData->addAuthor(ki18n("Sebastian Trueg"), KLocalizedString(), "trueg at k3b.org");
-    setAboutData( aboutData );
-
-    QHBoxLayout* box = new QHBoxLayout( this );
-    box->setContentsMargins( 0, 0, 0, 0 );
-
-    KTextEdit* label = new KTextEdit( this );
-    label->setText( "<h2>K3b::Setup</h2>"
-                    + i18n("<p>This simple setup assistant is able to set the permissions needed by K3b in order to "
-                           "burn CDs and DVDs. "
-                           "<p>It does not take things like devfs or resmgr into account. In most cases this is not a "
-                           "problem but on some systems the permissions may be altered the next time you login or restart "
-                           "your computer. In those cases it is best to consult the distribution documentation."
-                           "<p><b>Caution:</b> Although K3b::Setup should not be able "
-                           "to mess up your system no guarantee can be given.") );
-    label->setReadOnly( true );
-    label->setFixedWidth( 200 );
-
-    QWidget* w = new QWidget( this );
-    setupUi( w );
-
-    // TODO: enable this and let root specify users
-    m_frameUsers->hide();
-
-    box->addWidget( label );
-    box->addWidget( w );
-
-    d->devicesModel = new K3b::Setup::DevicesModel( this );
-    d->programsModel = new K3b::Setup::ProgramsModel(this );
-
-    connect( d->devicesModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
-             this, SLOT(slotDataChanged()) );
-    connect( d->devicesModel, SIGNAL(modelReset()),
-             this, SLOT(slotDataChanged()) );
-    connect( d->programsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
-             this, SLOT(slotDataChanged()) );
-    connect( d->programsModel, SIGNAL(modelReset()),
-             this, SLOT(slotDataChanged()) );
-    connect( m_checkUseBurningGroup, SIGNAL(toggled(bool)),
-             this, SLOT(slotBurningGroupChanged()) );
-    connect( m_editBurningGroup, SIGNAL(textChanged(QString)),
-             this, SLOT(slotBurningGroupChanged()) );
-    connect( m_editSearchPath, SIGNAL(changed()),
-             this, SLOT(slotSearchPathChanged()) );
-
-    m_viewDevices->setModel( d->devicesModel );
-    m_viewDevices->header()->setResizeMode( QHeaderView::ResizeToContents );
-    m_viewPrograms->setModel( d->programsModel );
-    m_viewPrograms->header()->setResizeMode( QHeaderView::ResizeToContents );
-
-    setNeedsAuthorization(true);
-
-    load();
-}
-
-
-K3bSetup::~K3bSetup()
-{
-    delete d->config;
-    delete d;
-}
-
-
-QString K3bSetup::quickHelp() const
-{
-    return i18n("<h2>K3b::Setup</h2>"
-                "<p>This simple setup assistant is able to set the permissions needed by K3b in order to "
-                "burn CDs and DVDs."
-                "<p>It does not take into account devfs or resmgr, or similar. In most cases this is not a "
-                "problem, but on some systems the permissions may be altered the next time you login or restart "
-                "your computer. In these cases it is best to consult the distribution's documentation."
-                "<p>The important task that K3b::Setup performs is grant write access to the CD and DVD devices."
-                "<p><b>Caution:</b> Although K3b::Setup should not be able "
-                "to damage your system, no guarantee can be given.");
-}
-
-
-void K3bSetup::defaults()
-{
-    m_checkUseBurningGroup->setChecked(false);
-    m_editBurningGroup->setText( "burning" );
-
-    d->devicesModel->defaults();
-    d->programsModel->defaults();
-}
-
-
-void K3bSetup::load()
-{
-    d->devicesModel->load( *d->config );
-    d->programsModel->load( *d->config );
-
-    KConfigGroup grp(d->config, "General Settings" );
-    m_checkUseBurningGroup->setChecked( grp.readEntry( "use burning group", false ) );
-    m_editBurningGroup->setText( grp.readEntry( "burning group", "burning" ) );
-
-    // load search path
-    m_editSearchPath->clear();
-    m_editSearchPath->insertStringList( d->programsModel->searchPaths() );
-}
-
-
-void K3bSetup::save()
-{
-    QString burningGroup = m_editBurningGroup->text();
-
-    if( m_checkUseBurningGroup->isChecked() && !burningGroup.isEmpty() ) {
-        if( !getgrnam( burningGroup.toLocal8Bit() ) ) {
-            KMessageBox::error( this, i18n( "There is no group \"%1\".", burningGroup ) );
-            QTimer::singleShot( 0, this, SLOT(slotDataChanged()) );
-            return;
-        }
-    }
-
-    KConfigGroup grp(d->config, "General Settings" );
-    grp.writeEntry( "use burning group", m_checkUseBurningGroup->isChecked() );
-    grp.writeEntry( "burning group", burningGroup.isEmpty() ? QString("burning") : burningGroup );
-    grp.sync();
-
-    d->devicesModel->save( *d->config );
-    d->programsModel->save( *d->config );
-
-    QVariantMap args;
-    // Set burning group name as first argument
-    if( m_checkUseBurningGroup->isChecked() && !m_editBurningGroup->text().isEmpty() )
-        args["burningGroup"] = m_editBurningGroup->text();
-    else
-        args["burningGroup"] = QString();
-
-    // Set devices list as second argument
-    args["devices"] =  d->devicesModel->selectedDevices();
-
-    // Set programs list as third argument
-    QVariantList programs;
-    Q_FOREACH( const K3b::Setup::ProgramItem& item, d->programsModel->selectedPrograms() )
-    {
-        programs << QVariant::fromValue( item );
-    }
-    args["programs"] = programs;
-
-    KAuth::Action *action = authAction();
-    action->setArguments(args);
-
-    KAuth::ActionReply reply = action->execute();
-
-    if (reply.failed()) {
-        // TODO: We can give some more details about the error here
-        kDebug() << reply.errorCode() << reply.errorDescription();
-        KMessageBox::error( this, i18n("Cannot run worker.") );
-        emit changed( true );
-    } else {
-        // Success!!
-        QStringList updated = reply.data()["updated"].toStringList();
-        QStringList failedToUpdate = reply.data()["failedToUpdate"].toStringList();
-        kDebug() << "Objects updated: " << updated;
-        kDebug() << "Objects failed to update: " << failedToUpdate;
-
-        if( !failedToUpdate.isEmpty() )
-            KMessageBox::errorList( this, i18n("Following devices and programs could not be updated:"), failedToUpdate );
-
-        // WE MAY USE "newgrp -" to reinitialize the environment if we add users to a group
-
-        d->devicesModel->update();
-        d->programsModel->update();
-    }
-}
-
-
-void K3bSetup::slotDataChanged()
-{
-    KConfigGroup grp(d->config, "General Settings" );
-    bool useBurningGroupChanged = m_checkUseBurningGroup->isChecked() != grp.readEntry( "use burning group", false );
-    bool burningGroupChanged = m_checkUseBurningGroup->isChecked() && m_editBurningGroup->text() != grp.readEntry( "burning group", "burning" );
-
-    emit changed(
-        useBurningGroupChanged ||
-        burningGroupChanged ||
-        d->devicesModel->changesNeeded() ||
-        d->programsModel->changesNeeded() );
-}
-
-
-void K3bSetup::slotBurningGroupChanged()
-{
-    if( m_checkUseBurningGroup->isChecked() ) {
-        d->devicesModel->setBurningGroup( m_editBurningGroup->text() );
-        d->programsModel->setBurningGroup( m_editBurningGroup->text() );
-    }
-    else {
-        d->devicesModel->setBurningGroup( QString() );
-        d->programsModel->setBurningGroup( QString() );
-    }
-
-    slotDataChanged();
-}
-
-
-void K3bSetup::slotSearchPathChanged()
-{
-    d->programsModel->setSearchPaths( m_editSearchPath->items() );
-}
-
-#include "k3bsetup.moc"
diff --git a/k3bsetup/k3bsetup.desktop b/k3bsetup/k3bsetup.desktop
deleted file mode 100644
index ec6a54b..0000000
--- a/k3bsetup/k3bsetup.desktop
+++ /dev/null
@@ -1,212 +0,0 @@
-[Desktop Entry]
-Encoding=UTF-8
-Comment=K3bSetup – modify permission for CD/DVD burning with K3b
-Comment[bg]=Настройки на K3b - промяна на правата за запис на CD/DVD
-Comment[bs]=K3b‑postava — mijenja dozvole za rezanje diskova K3bom
-Comment[ca]=K3bSetup - modifica els permisos per gravar CD/DVD amb el K3b
-Comment[ca at valencia]=K3bSetup - modifica els permisos per gravar CD/DVD amb el K3b
-Comment[cs]=K3bSetup - upravit oprávnění pro vypalování CD/DVD s K3b
-Comment[csb]=K3bSetup - mòdifikùje przëstsp dlô wëpôlaniô CD/DVD z K3b
-Comment[da]=K3bSetup – ændr rettigheder til cd-/dvd-brænding med K3b
-Comment[de]=K3b-Einrichtungsassistent – Zugriffsrechte zum Brennen mit K3b anpassen
-Comment[el]=K3bSetup – τροποποίηση δικαιωμάτων για εγγραφή CD/DVD με το K3b
-Comment[en_GB]=K3bSetup – modify permission for CD/DVD burning with K3b
-Comment[es]=K3bSetup - modificar los permisos para la grabación de CD/DVD con K3b
-Comment[et]=K3b seadistamine - võimalus muuta õigusi CD/DVD kirjutamiseks K3b-ga
-Comment[fi]=K3bSetup – muokkaa CD- ja DVD-polton oikeuksia K3b:tä varten
-Comment[fr]=K3bSetup - modifier les droits d'accès pour graver des CD / DVD avec K3b
-Comment[he]=K3bSetup 2 -  שינוי הרשאות עבור צריבת תקליטורי CD/DVD עם K3b
-Comment[hr]=Postavke K3b-a – promijenite dopuštenja za snimanje CD-a i DVD-a pomoću K3b-a
-Comment[hu]=K3b-beállító - jogosultságbeállítás CD/DVD-íráshoz a K3b-ben
-Comment[is]=K3bUppsetning – breyta heimildum fyrir CD/DVD brennslu með K3b
-Comment[it]=K3bSetup - modifica i permessi per scrivere CD/DVD con K3b
-Comment[ja]=K3bSetup - K3b で CD/DVD に書き込むための権限を設定
-Comment[km]=K3bSetup - កែប្រែ​សិទ្ធិ​សម្រាប់​ដុត​ស៊ីឌី/ឌីវីឌី​​ដោយ​ប្រើ K3b
-Comment[ko]=K3bSetup – K3b로 CD/DVD를 쓰기 위한 권한 조정
-Comment[lt]=K3bSetup - pakeiskite leidimus CD/DVD kūrimui su K3b
-Comment[nb]=K3bSetup  – endre tillatelser for CD-/DVD-brenning med K3b
-Comment[nds]=K3b-Inrichthölper – Verlöven för't Brennen vun CDs oder DVDs mit K3b ännern
-Comment[nl]=K3bSetup - stelt de toegangsrechten in voor cd/dvd-branden met K3b
-Comment[nn]=K3bSetup – endra løyva for CD- og DVD-brenning med K3b
-Comment[pl]=K3bSetup - modyfikacja uprawnień do nagrywania płyt CD/DVD za pomocą K3b
-Comment[pt]=K3bSetup - modificar as permissões para a gravação de CDs/DVDs com o K3b
-Comment[pt_BR]=Configurações avançadas do K3b - modifica as permissões para gravação de CD/DVD com o K3b
-Comment[ro]=K3bSetup – modificați permisiunile de scriere CD/DVD cu K3b
-Comment[ru]=K3bSetup – настроить права для записи при помощи K3b
-Comment[sk]=K3bSetup - upraviť práva pre napaľovanie CD/DVD s K3b
-Comment[sl]=K3b namestitev  - spremeni dovoljenja za zapisovanje CD/DVD-jev s K3b
-Comment[sr]=К3б‑постава — мења дозволе за резање дискова К3бом
-Comment[sr at ijekavian]=К3б‑постава — мијења дозволе за резање дискова К3бом
-Comment[sr at ijekavianlatin]=K3b‑postava — mijenja dozvole za rezanje diskova K3bom
-Comment[sr at latin]=K3b‑postava — menja dozvole za rezanje diskova K3bom
-Comment[sv]=Ställ in K3b: ändra rättigheter för att bränna cd/dvd med K3b
-Comment[th]=K3bSetup - แก้ไขสิทธิ์ที่อนุญาตสำหรับการเขียนซีดี/ดีวีดีด้วย K3b
-Comment[tr]=K3bSetup - K3b ile CD/DVD yazdırma izinlerini ayarlayın
-Comment[uk]=K3bSetup — змініть права для запису КД/DVD у K3b
-Comment[x-test]=xxK3bSetup – modify permission for CD/DVD burning with K3bxx
-Comment[zh_CN]=K3bSetup - 修改使用 K3b 刻录 CD/DVD 的权限
-Comment[zh_TW]=K3bSetup - 修改以 K3b 進行 CD/DVD 燒錄的許可權限
-Exec=k3bsetup
-Keywords=K3bSetup,k3bsetup
-Keywords[bg]=K3bSetup2,k3bsetup2,Настройване на K3b
-Keywords[bs]=K3b‑postava,K3bSetup,k3bsetup
-Keywords[ca]=K3bSetup,k3bsetup
-Keywords[ca at valencia]=K3bSetup,k3bsetup
-Keywords[cs]=K3bSetup,k3bsetup
-Keywords[csb]=K3bSetup,k3bsetup
-Keywords[da]=K3bSetup,k3bsetup
-Keywords[de]=K3b, Einrichtungsassistent, Rechte, Setup
-Keywords[el]=K3bSetup,k3bsetup
-Keywords[en_GB]=K3bSetup,k3bsetup
-Keywords[es]=K3bSetup,k3bsetup
-Keywords[et]=K3bSetup,k3bsetup,k3b seadistamine
-Keywords[fi]=K3bSetup,k3bsetup
-Keywords[fr]=K3bSetup,k3bsetup
-Keywords[ga]=K3bSetup,k3bsetup
-Keywords[he]=K3bSetup,k3bsetup
-Keywords[hr]=Postavke K3b-a,postavke k3b-a
-Keywords[hu]=K3b-beállító,k3b-beállító
-Keywords[is]=K3bSetup,k3bsetup,K3bUppsetning
-Keywords[it]=K3bSetup,k3bsetup
-Keywords[ja]=K3bSetup,k3bsetup
-Keywords[km]=K3bSetup,k3bsetup
-Keywords[ko]=K3bSetup,k3bsetup
-Keywords[lt]=K3bSetup,k3bsetup
-Keywords[nb]=K3bSetup,k3bsetup
-Keywords[nds]=K3bSetup,k3bsetup,K3b-Inrichthölper
-Keywords[nl]=K3bSetup,k3bsetup
-Keywords[nn]=K3bSetup,k3bsetup
-Keywords[pl]=K3bSetup,k3bsetup
-Keywords[pt]=K3bSetup,k3bsetup
-Keywords[pt_BR]=Configurações avançadas do K3b,configurações avançadas do K3b
-Keywords[ro]=K3bSetup,k3bsetup
-Keywords[ru]=K3bSetup,k3bsetup
-Keywords[sk]=K3bSetup,k3bsetup
-Keywords[sl]=K3bSetup2,k3bsetup2,k3bnamestitev,K3bNamestitev
-Keywords[sq]=K3bSetup,k3bsetup
-Keywords[sr]=К3б‑постава,K3bSetup,k3bsetup
-Keywords[sr at ijekavian]=К3б‑постава,K3bSetup,k3bsetup
-Keywords[sr at ijekavianlatin]=K3b‑postava,K3bSetup,k3bsetup
-Keywords[sr at latin]=K3b‑postava,K3bSetup,k3bsetup
-Keywords[sv]=Ställ in K3b,k3bsetup
-Keywords[th]=K3bSetup,k3bsetup
-Keywords[tr]=K3bSetup,k3bsetup
-Keywords[uk]=K3bSetup,k3bsetup
-Keywords[x-test]=xxK3bSetup,k3bsetupxx
-Keywords[zh_CN]=K3bSetup,k3bsetup2
-Keywords[zh_TW]=K3bSetup,k3bsetup
-Name=K3bSetup
-Name[bg]=Настройки на K3b
-Name[bs]=K3bSetup
-Name[ca]=K3bSetup
-Name[ca at valencia]=K3bSetup
-Name[cs]=K3bSetup
-Name[csb]=K3bSetup
-Name[da]=K3bSetup
-Name[de]=K3b-Einrichtungsassistent
-Name[el]=K3bSetup
-Name[en_GB]=K3bSetup
-Name[eo]=Name=K3bSetup
-Name[es]=K3bSetup
-Name[et]=K3b seadistamine
-Name[eu]=K3bSetup
-Name[fi]=K3bSetup
-Name[fr]=K3bSetup
-Name[ga]=K3bSetup
-Name[gl]=K3bSetup
-Name[he]=K3bSetup
-Name[hne]=के3बीसेटअप
-Name[hr]=Postavke K3b-a
-Name[hsb]=K3bSetup
-Name[hu]=K3b-beállító
-Name[is]=K3bUppsetning
-Name[it]=K3bSetup
-Name[ja]=K3bSetup
-Name[km]=K3bSetup
-Name[ko]=K3bSetup
-Name[lt]=K3bSetup
-Name[lv]=K3bSetup
-Name[nb]=K3bSetup
-Name[nds]=K3b-Inrichthölper
-Name[ne]=K3bSetup
-Name[nl]=K3bSetup
-Name[nn]=K3bSetup
-Name[pa]=K3bਸੈੱਟਅੱਪ
-Name[pl]=K3bSetup
-Name[pt]=K3bSetup
-Name[pt_BR]=Configurações avançadas do K3b
-Name[ro]=K3bSetup
-Name[ru]=K3bSetup
-Name[sk]=K3bSetup
-Name[sl]=K3b namestitev
-Name[sq]=K3bSetup
-Name[sr]=К3б‑постава
-Name[sr at ijekavian]=К3б‑постава
-Name[sr at ijekavianlatin]=K3b‑postava
-Name[sr at latin]=K3b‑postava
-Name[sv]=Ställ in K3b
-Name[th]=K3bSetup
-Name[tr]=K3bSetup
-Name[ug]=K3bSetup
-Name[uk]=Налаштування K3b
-Name[x-test]=xxK3bSetupxx
-Name[zh_CN]=K3bSetup
-Name[zh_TW]=K3bSetup
-
-Terminal=false
-Type=Service
-Icon=k3b
-X-KDE-ServiceTypes=KCModule
-X-KDE-Library=kcm_k3bsetup
-X-KDE-ParentApp=kcontrol
-X-KDE-System-Settings-Parent-Category=system
-X-KDE-System-Settings-Parent-Category-V2=permissions
-X-KDE-Keywords=k3b,k3bsetup,cd,dvd
-Categories=Application;System;X-KDE-System;
-X-DocPath=k3b/index.html#pre-setup
-GenericName=CD/DVD/BD Burning Setup
-GenericName[bg]=Настройки на записа на CD и DVD
-GenericName[bs]=Podešavanje rezanja diskova
-GenericName[ca]=Arranjament de gravació de CD i DVD
-GenericName[ca at valencia]=Arranjament de gravació de CD i DVD
-GenericName[cs]=Nastavení vypalování CD/DVD/BD
-GenericName[csb]=Nastôwë wëpôlaniô CD/DVD/BD
-GenericName[da]=Opsætning af cd-/dvd-/bd-brænding
-GenericName[de]=CD/DVD/BD-Brennen einrichten
-GenericName[el]=Ρύθμιση εγγραφής CD/DVD/BD
-GenericName[en_GB]=CD/DVD/BD Burning Setup
-GenericName[es]=Configurar grabación de CD/DVD/BD
-GenericName[et]=CD/DVD/BD kirjutamise seadistamine
-GenericName[fi]=CD- ja DVD-polton asetusohjelma
-GenericName[fr]=Configuration de la gravure de CD / DVD / BD
-GenericName[he]=הגדרות צריבת CD/DVD/BD
-GenericName[hr]=Postavke snimanja CD-a/DVD-a/BD-a
-GenericName[hu]=CD-, DVD- és BD-írási beállítások
-GenericName[is]=Uppsetning CD/DVD/BD brennslu
-GenericName[it]=Impostazioni di scrittura per CD/DVD/BD
-GenericName[ja]=CD/DVD/BD 作成の設定
-GenericName[km]=រៀបចំ​ការ​ដុត​ស៊ីឌី/ឌីវីឌី/ប៊ីឌី
-GenericName[ko]=CD/DVD/BD 쓰기 설정
-GenericName[lt]=CD/DVD/BD kūrimo sąranka
-GenericName[nb]=Oppsett av CD-  DVD- og BD-brenning
-GenericName[nds]=Brennen vun CD, DVD un BD instellen
-GenericName[nl]=cd/dvd/bd-branden instellen
-GenericName[nn]=Oppsett av CD-, DVD- og BD-brenning
-GenericName[pl]=Konfiguracja nagrywania płyt CD/DVD/BD
-GenericName[pt]=Configuração da Gravação de CDs/DVDs/BDs
-GenericName[pt_BR]=Configuração da gravação de CD/DVD/BD
-GenericName[ro]=Configurare scriere CD/DVD/BD
-GenericName[ru]=Параметр записи CD/DVD/BD
-GenericName[sk]=Nastavenie napaľovania CD/DVD/BD
-GenericName[sl]=Namestitev za zapisovanje CD-jev, DVD-jev in BD-jev
-GenericName[sr]=Подешавање резања дискова
-GenericName[sr at ijekavian]=Подешавање резања дискова
-GenericName[sr at ijekavianlatin]=Podešavanje rezanja diskova
-GenericName[sr at latin]=Podešavanje rezanja diskova
-GenericName[sv]=Cd, dvd och bd-bränninställning
-GenericName[th]=การตั้งค่าการเขียนแผ่นซีดีและดีวีดี
-GenericName[tr]=D/DVD/BD Yazma Yapılandırması
-GenericName[uk]=Налаштування запису КД, DVD та BD
-GenericName[x-test]=xxCD/DVD/BD Burning Setupxx
-GenericName[zh_CN]=CD/DVD/BD 刻录设置
-GenericName[zh_TW]=CD/DVD/BD 燒錄設定
diff --git a/k3bsetup/k3bsetup.h b/k3bsetup/k3bsetup.h
deleted file mode 100644
index c83d9ff..0000000
--- a/k3bsetup/k3bsetup.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *
- * Copyright (C) 2003-2009 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
- * Copyright (C) 2010 Dario Freddi <drf at kde.org>
- *
- * This file is part of the K3b project.
- * Copyright (C) 1998-2009 Sebastian Trueg <trueg at k3b.org>
- *
- * 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.
- * See the file "COPYING" for the exact licensing terms.
- */
-
-
-#ifndef _K3BSETUP_H_
-#define _K3BSETUP_H_
-
-#include "ui_base_k3bsetup.h"
-#include <KCModule>
-#include <QStringList>
-
-class K3bSetup : public KCModule, public Ui::base_K3bSetup
-{
-    Q_OBJECT
-
-public:
-    K3bSetup( QWidget* parent = 0, const QVariantList& args = QVariantList() );
-    ~K3bSetup();
-
-    QString quickHelp() const;
-
-    void defaults();
-    void load();
-    void save();
-
-private Q_SLOTS:
-    void slotDataChanged();
-    void slotBurningGroupChanged();
-    void slotSearchPathChanged();
-
-private:
-    class Private;
-    Private* d;
-};
-
-#endif
diff --git a/k3bsetup/k3bsetupdevicesmodel.cpp b/k3bsetup/k3bsetupdevicesmodel.cpp
deleted file mode 100644
index f418bce..0000000
--- a/k3bsetup/k3bsetupdevicesmodel.cpp
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- *
- * Copyright (C) 2003-2009 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
- *
- * This file is part of the K3b project.
- * Copyright (C) 1998-2009 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
- *
- * 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.
- * See the file "COPYING" for the exact licensing terms.
- */
-
-#include "k3bsetupdevicesmodel.h"
-#include "k3bdevicemanager.h"
-#include "k3bdevice.h"
-
-#include <KConfig>
-#include <KConfigGroup>
-#include <KDebug>
-#include <KLocale>
-
-#include <QFile>
-#include <QFileInfo>
-#include <QSet>
-
-#include <sys/stat.h>
-
-namespace K3b {
-namespace Setup {
-
-class DevicesModel::Private
-{
-public:
-    Device::DeviceManager* deviceManager;
-    QSet<Device::Device*> selectedDevices;
-    QString burningGroup;
-
-    bool needChangePermissions( const Device::Device* device );
-};
-
-
-bool DevicesModel::Private::needChangePermissions( const Device::Device* device )
-{
-    struct stat s;
-    if( ::stat( QFile::encodeName( device->blockDeviceName() ), &s ) == 0 ) {
-
-        QFileInfo fi( device->blockDeviceName() );
-        int perm = s.st_mode & 0000777;
-
-        if( !burningGroup.isEmpty() ) {
-            if( perm != 0000660 || fi.group() != burningGroup )
-                return true;
-        }
-        else if( perm != 0000666 ) {
-             return true;
-        }
-    }
-    return false;
-}
-
-
-DevicesModel::DevicesModel( QObject* parent )
-:
-    QAbstractItemModel( parent ),
-    d( new Private )
-{
-    d->deviceManager = new Device::DeviceManager( this );
-    d->deviceManager->scanBus();
-    connect( d->deviceManager, SIGNAL(changed()), this, SLOT(update()) );
-}
-
-
-DevicesModel::~DevicesModel()
-{
-    delete d;
-}
-
-
-void DevicesModel::load( const KConfig& config )
-{
-    d->selectedDevices.clear();
-    d->deviceManager->readConfig( config.group( "Devices" ) );
-    reset();
-}
-
-
-void DevicesModel::defaults()
-{
-    d->selectedDevices.clear();
-    reset();
-}
-
-
-void DevicesModel::save( KConfig& config ) const
-{
-    d->deviceManager->saveConfig( config.group( "Devices" ) );
-}
-
-
-QStringList DevicesModel::selectedDevices() const
-{
-    QStringList deviceNodes;
-    Q_FOREACH( Device::Device* device, d->selectedDevices )
-    {
-        deviceNodes.push_back( device->blockDeviceName() );
-    }
-    return deviceNodes;
-}
-
-
-bool DevicesModel::changesNeeded() const
-{
-    return !selectedDevices().isEmpty();
-}
-
-        
-Device::Device* DevicesModel::deviceForIndex( const QModelIndex& index ) const
-{
-    if( index.isValid() )
-        return static_cast<Device::Device*>( index.internalPointer() );
-    else
-        return 0;
-}
-
-
-QModelIndex DevicesModel::indexForDevice( Device::Device* device ) const
-{
-    if( device != 0 && !d->deviceManager->allDevices().isEmpty() )
-    {
-        int row = d->deviceManager->allDevices().indexOf( device );
-        return createIndex( row, 0, device );
-    }
-    else
-        return QModelIndex();
-}
-
-
-QVariant DevicesModel::data( const QModelIndex& index, int role ) const
-{
-    Device::Device* device = deviceForIndex( index );
-    if( device == 0 )
-        return QVariant();
-    
-    if( role == Qt::DisplayRole &&  index.column() >= 0 && index.column() <= 3 ) {
-        if( index.column() == 0 ) {
-            return QString(device->vendor() + " " + device->description());
-        }
-        else if( index.column() == 1 ) {
-            return device->blockDeviceName();
-        }
-        else {
-            struct stat s;
-            if( ::stat( QFile::encodeName( device->blockDeviceName() ), &s ) == 0 ) {
-
-                QFileInfo fi( device->blockDeviceName() );
-                int perm = s.st_mode & 0000777;
-
-                if( index.column() == 2 ) {
-                    return QString(QString::number( perm, 8 ).rightJustified( 3, '0' ) + " " + fi.owner() + "." + fi.group());
-                }
-                else if( !d->burningGroup.isEmpty() ) {
-                    // we ignore the device's owner here
-                    if( perm != 0000660 || fi.group() != d->burningGroup )
-                        return QString("660 " + fi.owner() + "." + d->burningGroup);
-                    else
-                        return i18n("no change");
-                }
-                else {
-                    // we ignore the device's owner and group here
-                    if( perm != 0000666 )
-                        return QString("666 " + fi.owner() + "." + fi.group());
-                    else
-                        return i18n("no change");
-                }
-            }
-            else {
-                kDebug() << "(K3bSetup) unable to stat " << device->blockDeviceName();
-                return QVariant();
-            }
-        }
-    }
-    else if( role == Qt::CheckStateRole && index.column() == 0 && d->needChangePermissions( device ) ) {
-        if( d->selectedDevices.contains( device ) )
-            return Qt::Checked;
-        else
-            return Qt::Unchecked;
-    }
-    else
-        return QVariant();
-}
-
-
-bool DevicesModel::setData( const QModelIndex& index, const QVariant& value, int role )
-{
-    if( Device::Device* device = deviceForIndex( index ) )
-    {
-        if( role == Qt::CheckStateRole ) {
-            if( value.toInt() == Qt::Unchecked && d->selectedDevices.contains( device ) ) {
-                d->selectedDevices.remove( device );
-                emit dataChanged( index, index );
-                return true;
-            }
-            else if( value.toInt() == Qt::Checked && !d->selectedDevices.contains( device ) ) {
-                d->selectedDevices.insert( device );
-                emit dataChanged( index, index );
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
-
-Qt::ItemFlags DevicesModel::flags( const QModelIndex& index ) const
-{
-    if( Device::Device* device = deviceForIndex( index ) )
-    {
-        if( index.column() == 0 && d->needChangePermissions( device ) )
-            return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
-        else
-            return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
-    }
-    else
-        return 0;
-}
-
-
-QVariant DevicesModel::headerData( int section, Qt::Orientation orientation, int role ) const
-{
-    if( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
-        switch( section )
-        {
-            case 0: return i18n( "Device" );
-            case 1: return i18n( "Devicenode" );
-            case 2: return i18n( "Permissions" );
-            case 3: return i18n( "New permissions" );
-            default: return QVariant();
-        }
-    }
-    else
-        return QVariant();
-}
-
-
-QModelIndex DevicesModel::index( int row, int column, const QModelIndex& parent ) const
-{
-    if( hasIndex(row, column, parent) && !parent.isValid() ) {
-        Device::Device* device = d->deviceManager->allDevices().at( row );
-        if( device != 0 )
-            return createIndex( row, column, device );
-        else {
-            kDebug() << "device manager returned empty device!";
-            return QModelIndex();
-        }
-    }
-    else
-        return QModelIndex();
-}
-
-
-QModelIndex DevicesModel::parent( const QModelIndex& index ) const
-{
-    Q_UNUSED( index );
-    return QModelIndex();
-}
-
-
-int DevicesModel::rowCount( const QModelIndex& parent ) const
-{
-    if( !parent.isValid() )
-        return d->deviceManager->allDevices().size();
-    else
-        return 0;
-}
-
-
-int DevicesModel::columnCount( const QModelIndex& parent ) const
-{
-    Q_UNUSED( parent );
-    return 4;
-}
-
-
-void DevicesModel::setBurningGroup( const QString& burningGroup )
-{
-    if( burningGroup != d->burningGroup ) {
-        d->burningGroup = burningGroup;
-        
-        // Remove from the selected list all devices
-        // whose permissions don't need to be changed anymore
-        for( QSet<Device::Device*>::iterator device = d->selectedDevices.begin();
-             device != d->selectedDevices.end(); )
-        {
-            if( !d->needChangePermissions( *device ) )
-                device = d->selectedDevices.erase( device );
-            else
-                ++device;
-        }
-        reset();
-    }
-}
-
-
-void DevicesModel::update()
-{
-    // Remove from unselected devices list all devices
-    // that are not present anymore in device manager
-    QSet<Device::Device*> devices = d->deviceManager->allDevices().toSet();
-    d->selectedDevices.intersect( devices );
-    reset();
-}
-
-} // namespace Setup
-} // namespace K3b
-
-#include "k3bsetupdevicesmodel.moc"
diff --git a/k3bsetup/k3bsetupdevicesmodel.h b/k3bsetup/k3bsetupdevicesmodel.h
deleted file mode 100644
index 10175b3..0000000
--- a/k3bsetup/k3bsetupdevicesmodel.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *
- * Copyright (C) 2003-2009 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
- *
- * This file is part of the K3b project.
- * Copyright (C) 1998-2009 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
- *
- * 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.
- * See the file "COPYING" for the exact licensing terms.
- */
-
-#ifndef _K3BSETUPDEVICESMODEL_H_
-#define _K3BSETUPDEVICESMODEL_H_
-
-#include <QAbstractItemModel>
-#include <QStringList>
-
-class KConfig;
-
-namespace K3b {
-    
-namespace Device {
-    class Device;
-}
-    
-namespace Setup {
-
-    class DevicesModel : public QAbstractItemModel
-    {
-    Q_OBJECT
-
-    public:
-        DevicesModel( QObject* parent = 0 );
-        ~DevicesModel();
-
-        void load( const KConfig& config );
-        void save( KConfig& config ) const;
-        void defaults();
-
-        QStringList selectedDevices() const;
-        bool changesNeeded() const;
-        
-        Device::Device* deviceForIndex( const QModelIndex& index ) const;
-        QModelIndex indexForDevice( Device::Device* device ) const;
-
-        QVariant data( const QModelIndex& index, int role ) const;
-        bool setData( const QModelIndex& index, const QVariant& value, int role );
-        Qt::ItemFlags flags( const QModelIndex& index ) const;
-        QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
-        QModelIndex index( int row, int column, const QModelIndex& parent = QModelIndex() ) const;
-        QModelIndex parent( const QModelIndex& index ) const;
-        int rowCount( const QModelIndex& parent = QModelIndex() ) const;
-        int columnCount( const QModelIndex& parent = QModelIndex() ) const;
-
-    public Q_SLOTS:
-        void setBurningGroup( const QString& burningGroup );
-        void update();
-
-    private:
-        class Private;
-        Private* d;
-    };
-
-} // namespace Setup
-} // namespace K3b
-
-#endif
diff --git a/k3bsetup/k3bsetupprogramsmodel.h b/k3bsetup/k3bsetupprogramsmodel.h
deleted file mode 100644
index 62cbcf8..0000000
--- a/k3bsetup/k3bsetupprogramsmodel.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *
- * Copyright (C) 2003-2009 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
- *
- * This file is part of the K3b project.
- * Copyright (C) 1998-2009 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
- *
- * 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.
- * See the file "COPYING" for the exact licensing terms.
- */
-
-#ifndef _K3BSETUPPROGRAMSMODEL_H_
-#define _K3BSETUPPROGRAMSMODEL_H_
-
-#include "k3bsetupprogramitem.h"
-#include <QAbstractItemModel>
-#include <QList>
-#include <QStringList>
-
-class KConfig;
-
-namespace K3b {
-    
-    class ExternalBin;
-    
-namespace Setup {
-
-    class ProgramsModel : public QAbstractItemModel
-    {
-        Q_OBJECT
-
-    public:
-        ProgramsModel( QObject* parent = 0 );
-        ~ProgramsModel();
-
-        void load( const KConfig& config );
-        void save( KConfig& config ) const;
-        void defaults();
-
-        QList<ProgramItem> selectedPrograms() const;
-        bool changesNeeded() const;
-        QStringList searchPaths() const;
-        
-        const ExternalBin* programForIndex( const QModelIndex& index ) const;
-        QModelIndex indexForProgram( const ExternalBin* program ) const;
-
-        QVariant data( const QModelIndex& index, int role ) const;
-        bool setData( const QModelIndex& index, const QVariant& value, int role );
-        Qt::ItemFlags flags( const QModelIndex& index ) const;
-        QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
-        QModelIndex index( int row, int column, const QModelIndex& parent = QModelIndex() ) const;
-        QModelIndex parent( const QModelIndex& index ) const;
-        int rowCount( const QModelIndex& parent = QModelIndex() ) const;
-        int columnCount( const QModelIndex& parent = QModelIndex() ) const;
-
-    public Q_SLOTS:
-        void setBurningGroup( const QString& burningGroup );
-        void setSearchPaths( const QStringList& searchPaths );
-        void update();
-
-    private:
-        class Private;
-        Private* d;
-    };
-
-} // namespace Setup
-} // namespace K3b
-
-#endif
diff --git a/libk3b/projects/k3bcdrecordwriter.cpp b/libk3b/projects/k3bcdrecordwriter.cpp
index bb42633..6557434 100644
--- a/libk3b/projects/k3bcdrecordwriter.cpp
+++ b/libk3b/projects/k3bcdrecordwriter.cpp
@@ -867,9 +867,7 @@ void K3b::CdrecordWriter::slotProcessExited( int exitCode, QProcess::ExitStatus
                 break;
             case PERMISSION_DENIED:
                 emit infoMessage( i18n("%1 has no permission to open the device.",QString("cdrecord")), MessageError );
-#ifdef BUILD_K3BSETUP
-                emit infoMessage( i18n("You may use K3bsetup to solve this problem."), MessageError );
-#endif
+                emit infoMessage( i18n("Modify device K3b settings to solve this problem."), MessageError );
                 break;
             case BUFFER_UNDERRUN:
                 emit infoMessage( i18n("Probably a buffer underrun occurred."), MessageError );
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 81f6ee0..75a82d5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -21,18 +21,24 @@ include_directories(
   ${libk3b_BINARY_DIR}/tools
   ${libk3b_BINARY_DIR}/projects
   ${libk3b_BINARY_DIR}/jobs
+  ${CMAKE_CURRENT_SOURCE_DIR}/helper
   ${CMAKE_CURRENT_SOURCE_DIR}/projects
   ${CMAKE_CURRENT_SOURCE_DIR}/projects/kostore/
   ${libk3b_SOURCE_DIR}/cddb
   )
 
-add_subdirectory( pics )
+add_subdirectory( helper )
 add_subdirectory( icons )
+add_subdirectory( pics )
 add_subdirectory( services )
 
 
 ########### next target ###############
 
+set(k3b_helper_SRCS
+  helper/k3bhelperprogramitem.cpp
+)
+
 set(k3b_project_SRCS
   projects/k3baudioburndialog.cpp
   projects/k3baudiocdtextwidget.cpp
@@ -139,6 +145,7 @@ set(k3b_option_SRCS
   option/k3bexternalbinmodel.cpp
   option/k3bexternalbinoptiontab.cpp
   option/k3bexternalbinparamsmodel.cpp
+  option/k3bexternalbinpermissionmodel.cpp
   option/k3badvancedoptiontab.cpp
   option/k3boptiondialog.cpp
   option/k3bdeviceoptiontab.cpp
@@ -266,6 +273,7 @@ qt4_generate_dbus_interface( ${CMAKE_CURRENT_SOURCE_DIR}/k3bdataprojectinterface
 qt4_add_dbus_adaptor( k3b_dbus_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.k3b.DataProject.xml k3bdataprojectinterface.h K3b::DataProjectInterface k3bdataprojectinterfaceadaptor K3bDataProjectInterfaceAdaptor )
 
 set(k3b_bin_SRCS
+  ${k3b_helper_SRCS}
   ${k3b_option_SRCS}
   ${k3b_misc_SRCS}
   ${k3b_project_SRCS}
@@ -293,6 +301,7 @@ target_link_libraries(k3b_bin
   k3bdevice
   k3b
   ${KCDDB_LIBRARIES}
+  ${KDE4_KDEUI_LIBS}
   ${KDE4_KFILE_LIBS}
   ${KDE4_KIO_LIBS}
   ${KDE4_KPARTS_LIBS}
diff --git a/src/helper/CMakeLists.txt b/src/helper/CMakeLists.txt
new file mode 100644
index 0000000..7abc385
--- /dev/null
+++ b/src/helper/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+kde4_add_executable(k3bhelper k3bhelper.cpp k3bhelperprogramitem.cpp)
+
+target_link_libraries(k3bhelper ${KDE4_KDECORE_LIBRARY})
+
+install(TARGETS k3bhelper DESTINATION ${LIBEXEC_INSTALL_DIR})
+
+kde4_install_auth_helper_files(k3bhelper org.kde.k3b root)
+
+kde4_install_auth_actions(org.kde.k3b k3b.actions)
diff --git a/k3bsetup/k3bsetup.actions b/src/helper/k3b.actions
similarity index 97%
rename from k3bsetup/k3bsetup.actions
rename to src/helper/k3b.actions
index dd0a011..41407a6 100644
--- a/k3bsetup/k3bsetup.actions
+++ b/src/helper/k3b.actions
@@ -1,4 +1,4 @@
-[org.kde.kcontrol.k3bsetup.save]
+[org.kde.k3b.updatepermissions]
 Name=Update device and programs permissions
 Name[bg]=Обновяване правата върху устройства и програми
 Name[bs]=Osvježi uređaje i dozvole programa
@@ -81,3 +81,8 @@ Description[uk]=Для оновлення прав доступу до прис
 Description[x-test]=xxAuthentication is required to update permissions of devices and programsxx
 Description[zh_TW]=更新裝置與程式的權限時需要驗證身份
 Policy=auth_admin
+
+[org.kde.k3b.addtogroup]
+Name=Adds current user to a specified group
+Description=Authentication is required to add current user to a group
+Policy=auth_admin
diff --git a/k3bsetup/k3bsetupworker.cpp b/src/helper/k3bhelper.cpp
similarity index 66%
rename from k3bsetup/k3bsetupworker.cpp
rename to src/helper/k3bhelper.cpp
index 40119bc..d427687 100644
--- a/k3bsetup/k3bsetupworker.cpp
+++ b/src/helper/k3bhelper.cpp
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
+ * Copyright (C) 2009-2011 Michal Malek <michalm at jabster.pl>
  * Copyright (C) 2010 Dario Freddi <drf at kde.org>
  *
  * This file is part of the K3b project.
@@ -13,21 +13,22 @@
  * See the file "COPYING" for the exact licensing terms.
  */
 
-#include "k3bsetupworker.h"
-#include "k3bsetupprogramitem.h"
+#include "k3bhelper.h"
+#include "k3bhelperprogramitem.h"
 
-#include <QFile>
-#include <QString>
-#include <QStringList>
+#include <QtCore/QFile>
+#include <QtCore/QProcess>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
 
+#include <grp.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#include <grp.h>
 
 namespace {
 
-bool updateDevicePermissions( struct group* g, const QString& device )
+bool updateDevicePermissions( ::group* g, const QString& device )
 {
     bool success = true;
     if( g != 0 ) {
@@ -45,7 +46,7 @@ bool updateDevicePermissions( struct group* g, const QString& device )
 }
 
 
-bool updateProgramPermissions( struct group* g, const QString& path, bool suid )
+bool updateProgramPermissions( ::group* g, const QString& path, bool suid )
 {
     bool success = true;
     if( g != 0 ) {
@@ -81,24 +82,22 @@ bool updateProgramPermissions( struct group* g, const QString& path, bool suid )
 
 
 namespace K3b {
-namespace Setup {
 
-Worker::Worker()
+Helper::Helper()
 {
-    qRegisterMetaType<ProgramItem>();
-    qRegisterMetaTypeStreamOperators<ProgramItem>( "K3b::Setup::ProgramItem" );
+    qRegisterMetaType<HelperProgramItem>();
+    qRegisterMetaTypeStreamOperators<HelperProgramItem>( "K3b::HelperProgramItem" );
 }
-  
-ActionReply Worker::save( QVariantMap args )
+
+ActionReply Helper::updatepermissions( QVariantMap args )
 {
     QString burningGroup = args["burningGroup"].toString();
     QStringList devices = args["devices"].toStringList();
     QVariantList programs = args["programs"].value<QVariantList>();
         
-    struct group* g = 0;
+    ::group* g = 0;
     if( !burningGroup.isEmpty() ) {
-        // TODO: create the group if it's not there
-        g = getgrnam( burningGroup.toLocal8Bit() );
+        g = ::getgrnam( burningGroup.toLocal8Bit() );
     }
     
     QStringList updated;
@@ -114,7 +113,7 @@ ActionReply Worker::save( QVariantMap args )
     
     Q_FOREACH( const QVariant& v, programs )
     {
-        ProgramItem program = v.value<ProgramItem>();
+        HelperProgramItem program = v.value<HelperProgramItem>();
         
         if( !program.m_path.isEmpty() && updateProgramPermissions( g, program.m_path, program.m_needSuid ) )
             updated.push_back( program.m_path );
@@ -127,13 +126,32 @@ ActionReply Worker::save( QVariantMap args )
     data["updated"] = updated;
     data["failedToUpdate"] = failedToUpdate;
     reply.setData(data);
-    
+
+    return reply;
+}
+
+ActionReply Helper::addtogroup( QVariantMap args )
+{
+    const QString groupName = args["groupName"].toString();
+    const QString userName = args["userName"].toString();
+
+    QProcess gpasswd;
+    int errorCode = gpasswd.execute( "gpasswd", QStringList() << "--add" << userName << groupName );
+
+    ActionReply reply;
+    if( errorCode == 0 ) {
+        reply = KAuth::ActionReply::SuccessReply;
+    } else {
+        reply = KAuth::ActionReply::HelperErrorReply;
+        reply.setErrorCode( errorCode );
+        reply.setErrorDescription( QString::fromLocal8Bit( gpasswd.readAllStandardError().data() ) );
+    }
+
     return reply;
 }
 
-} // namespace Setup
 } // namespace K3b
 
-KDE4_AUTH_HELPER_MAIN("org.kde.kcontrol.k3bsetup", K3b::Setup::Worker)
+KDE4_AUTH_HELPER_MAIN("org.kde.k3b", K3b::Helper)
 
-#include "k3bsetupworker.moc"
+#include "k3bhelper.moc"
diff --git a/k3bsetup/k3bsetupworker.h b/src/helper/k3bhelper.h
similarity index 65%
rename from k3bsetup/k3bsetupworker.h
rename to src/helper/k3bhelper.h
index 4a5f67d..08c9b8e 100644
--- a/k3bsetup/k3bsetupworker.h
+++ b/src/helper/k3bhelper.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
+ * Copyright (C) 2009-2011 Michal Malek <michalm at jabster.pl>
  * Copyright (C) 2010 Dario Freddi <drf at kde.org>
  *
  * This file is part of the K3b project.
@@ -13,22 +13,21 @@
  * See the file "COPYING" for the exact licensing terms.
  */
 
-#ifndef _K3BSETUPWORKER_H_
-#define _K3BSETUPWORKER_H_
+#ifndef K3BHELPER_H
+#define K3BHELPER_H
 
 #include <kauth.h>
 
 using namespace KAuth;
  
 namespace K3b {
-namespace Setup {
  
-class Worker : public QObject
+class Helper : public QObject
 {
     Q_OBJECT
-    
+
 public:
-    Worker();
+    Helper();
 
 public slots:
     /**
@@ -36,13 +35,18 @@ public slots:
      * @param burningGroup name of the burning group. If not set burning group will not be used
      * @param devices list of devices which will have updated permissions
      * @param programs list of the programs which will have updated permissions. Each element
-     *                 of the list is a @see K3b::Setup::ProgramItem object
+     *                 of the list is a @see K3b::HelperProgramItem object
      */
-    ActionReply save( QVariantMap args );
+    ActionReply updatepermissions( QVariantMap args );
 
+    /**
+     * Adds user to a specified group
+     * @param groupName name of the group
+     * @param userName name of the user
+     */
+    ActionReply addtogroup( QVariantMap args );
 };
 
-} // namespace Setup
 } // namespace K3b
  
-#endif
+#endif // K3BHELPER_H
diff --git a/k3bsetup/k3bsetupprogramitem.cpp b/src/helper/k3bhelperprogramitem.cpp
similarity index 64%
rename from k3bsetup/k3bsetupprogramitem.cpp
rename to src/helper/k3bhelperprogramitem.cpp
index 2b469ec..b95bfce 100644
--- a/k3bsetup/k3bsetupprogramitem.cpp
+++ b/src/helper/k3bhelperprogramitem.cpp
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright (C) 2009-2010 Michal Malek <michalm at jabster.pl>
+ * Copyright (C) 2009-2011 Michal Malek <michalm at jabster.pl>
  * Copyright (C)      2010 Dario Freddi <drf at kde.org>
  *
  * This file is part of the K3b project.
@@ -13,32 +13,30 @@
  * See the file "COPYING" for the exact licensing terms.
  */
 
-#include "k3bsetupprogramitem.h"
+#include "k3bhelperprogramitem.h"
 
 namespace K3b {
-namespace Setup {
 
-ProgramItem::ProgramItem()
+HelperProgramItem::HelperProgramItem()
 {
 }
 
-ProgramItem::ProgramItem( const QString& path, bool needSuid )
+HelperProgramItem::HelperProgramItem( const QString& path, bool needSuid )
 :
     m_path( path ),
     m_needSuid( needSuid )
 {
 }
 
-} // namespace Setup
 } // namespace K3b
 
-QDataStream& operator<<( QDataStream& data, const K3b::Setup::ProgramItem& item )
+QDataStream& operator<<( QDataStream& data, const K3b::HelperProgramItem& item )
 {
     data << item.m_path << item.m_needSuid;
     return data;
 }
 
-const QDataStream& operator>>( QDataStream& data, K3b::Setup::ProgramItem& item )
+const QDataStream& operator>>( QDataStream& data, K3b::HelperProgramItem& item )
 {
     data >> item.m_path >> item.m_needSuid;
     return data;
diff --git a/k3bsetup/k3bsetupprogramitem.h b/src/helper/k3bhelperprogramitem.h
similarity index 51%
rename from k3bsetup/k3bsetupprogramitem.h
rename to src/helper/k3bhelperprogramitem.h
index ecbbd4f..9ed7515 100644
--- a/k3bsetup/k3bsetupprogramitem.h
+++ b/src/helper/k3bhelperprogramitem.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright (C) 2009-2010 Michal Malek <michalm at jabster.pl>
+ * Copyright (C) 2009-2011 Michal Malek <michalm at jabster.pl>
  * Copyright (C)      2010 Dario Freddi <drf at kde.org>
  *
  * This file is part of the K3b project.
@@ -13,31 +13,29 @@
  * See the file "COPYING" for the exact licensing terms.
  */
 
-#ifndef _K3BSETUPPROGRAMITEM_H_
-#define _K3BSETUPPROGRAMITEM_H_
+#ifndef K3BHELPERPROGRAMITEM_H
+#define K3BHELPERPROGRAMITEM_H
 
-#include <QMetaType>
-#include <QString>
+#include <QtCore/QMetaType>
+#include <QtCore/QString>
 
 namespace K3b {
-namespace Setup {
 
-class ProgramItem
+class HelperProgramItem
 {
 public:
-    ProgramItem();
-    ProgramItem( const QString& path, bool needSuid );
-    
+    HelperProgramItem();
+    HelperProgramItem( const QString& path, bool needSuid );
+
     QString m_path;
     bool m_needSuid;
 };
 
-} // namespace Setup
 } // namespace K3b
 
-Q_DECLARE_METATYPE( K3b::Setup::ProgramItem )
+Q_DECLARE_METATYPE( K3b::HelperProgramItem )
 
-QDataStream& operator<<( QDataStream& stream, const K3b::Setup::ProgramItem& item );
-const QDataStream& operator>>( QDataStream& stream, K3b::Setup::ProgramItem& item );
+QDataStream& operator<<( QDataStream& stream, const K3b::HelperProgramItem& item );
+const QDataStream& operator>>( QDataStream& stream, K3b::HelperProgramItem& item );
 
-#endif
+#endif // K3BHELPERPROGRAMITEM_H
diff --git a/src/k3b.cpp b/src/k3b.cpp
index 167954e..84ded54 100644
--- a/src/k3b.cpp
+++ b/src/k3b.cpp
@@ -63,7 +63,6 @@
 #include "misc/k3bmediaformattingdialog.h"
 #include "option/k3boptiondialog.h"
 #include "projects/k3bdatamultisessionimportdialog.h"
-#include "config-k3b.h"
 
 // include files for KDE
 #include <kaboutdata.h>
@@ -458,14 +457,6 @@ void K3b::MainWindow::initActions()
     actionSettingsConfigure->setToolTip( i18n("Configure K3b settings") );
     actionSettingsConfigure->setStatusTip( actionSettingsConfigure->toolTip() );
 
-#ifdef BUILD_K3BSETUP
-    KAction* actionSettingsK3bSetup = new KAction( KIcon( "configure" ), i18n("&Setup System Permissions..."), this );
-    actionSettingsK3bSetup->setToolTip( i18n("Setup the system permissions") );
-    actionSettingsK3bSetup->setStatusTip( actionSettingsK3bSetup->toolTip() );
-    actionCollection()->addAction( "settings_k3bsetup", actionSettingsK3bSetup );
-    connect( actionSettingsK3bSetup, SIGNAL(triggered(bool)), this, SLOT(slotK3bSetup()) );
-#endif
-
     KAction* actionHelpSystemCheck = new KAction( i18n("System Check"), this );
     actionHelpSystemCheck->setToolTip( i18n("Checks system configuration") );
     actionHelpSystemCheck->setStatusTip( actionHelpSystemCheck->toolTip() );
@@ -1378,15 +1369,6 @@ void K3b::MainWindow::slotProjectAddFiles()
 }
 
 
-void K3b::MainWindow::slotK3bSetup()
-{
-    QStringList args;
-    args << "k3bsetup" << "--lang" << KGlobal::locale()->language();
-    if( !KProcess::startDetached( K3b::findExe("kcmshell4"), args ) )
-        KMessageBox::error( 0, i18n("Unable to start K3b::Setup.") );
-}
-
-
 void K3b::MainWindow::formatMedium( K3b::Device::Device* dev )
 {
     K3b::MediaFormattingDialog d( this );
diff --git a/src/k3b.h b/src/k3b.h
index 96da430..dfa30fe 100644
--- a/src/k3b.h
+++ b/src/k3b.h
@@ -101,7 +101,6 @@ namespace K3b {
         void slotVideoDvdRip();
         void videoCdRip( K3b::Device::Device* );
         void slotVideoCdRip();
-        void slotK3bSetup();
 
         void showDiskInfo( K3b::Device::Device* );
 
diff --git a/src/k3bsystemproblemdialog.cpp b/src/k3bsystemproblemdialog.cpp
index 5d63a01..dc573f3 100644
--- a/src/k3bsystemproblemdialog.cpp
+++ b/src/k3bsystemproblemdialog.cpp
@@ -17,8 +17,9 @@
 #include <config-k3b.h>
 
 
-#include "k3bapplication.h"
 #include "k3bsystemproblemdialog.h"
+#include "k3b.h"
+#include "k3bapplication.h"
 #include "k3bthemedheader.h"
 #include "k3btitlelabel.h"
 #include "k3bexternalbinmanager.h"
@@ -82,7 +83,8 @@ K3b::SystemProblem::SystemProblem( Type t,
 
 
 K3b::SystemProblemDialog::SystemProblemDialog( const QList<K3b::SystemProblem>& problems,
-                                               bool showK3bSetupButton,
+                                               bool showDeviceSettingsButton,
+                                               bool showBinSettingsButton,
                                                QWidget* parent)
     : KDialog( parent )
 {
@@ -100,15 +102,14 @@ K3b::SystemProblemDialog::SystemProblemDialog( const QList<K3b::SystemProblem>&
     connect( closeButton, SIGNAL(clicked()), this, SLOT(close()) );
     m_checkDontShowAgain = new QCheckBox( i18n("Do not show again"), widget );
 
-    QPushButton* k3bsetupButton = 0;
-#ifdef BUILD_K3BSETUP
-    if( showK3bSetupButton ) {
-        k3bsetupButton = new QPushButton( i18n("Modify Permissions..."), widget );
-        connect( k3bsetupButton, SIGNAL(clicked()), this, SLOT(slotK3bSetup()) );
+    QPushButton* configureButton = new QPushButton( KIcon( "configure" ), i18n("Configure K3b..."), widget );
+    if( showDeviceSettingsButton ) {
+        connect( configureButton, SIGNAL(clicked()), SLOT(slotShowDeviceSettings()) );
+    } else if( showBinSettingsButton ) {
+        connect( configureButton, SIGNAL(clicked()), SLOT(slotShowBinSettings()) );
+    } else {
+        configureButton->hide();
     }
-#else
-    Q_UNUSED( showK3bSetupButton );
-#endif
 
     // setup the problem view
     // ---------------------------------------------------------------------------------------------------
@@ -122,9 +123,7 @@ K3b::SystemProblemDialog::SystemProblemDialog( const QList<K3b::SystemProblem>&
     grid->addWidget( m_checkDontShowAgain, 2, 0 );
     QHBoxLayout* buttonBox = new QHBoxLayout;
     buttonBox->setContentsMargins( 0, 0, 0, 0 );
-    if( k3bsetupButton != 0 ) {
-        buttonBox->addWidget( k3bsetupButton );
-    }
+    buttonBox->addWidget( configureButton );
     buttonBox->addWidget( closeButton );
     grid->addLayout( buttonBox, 2, 1 );
     grid->setColumnStretch( 0, 1 );
@@ -175,13 +174,8 @@ void K3b::SystemProblemDialog::closeEvent( QCloseEvent* e )
 void K3b::SystemProblemDialog::checkSystem( QWidget* parent, NotificationLevel level )
 {
     QList<K3b::SystemProblem> problems;
-    bool showK3bSetupButton = false;
-
-#ifdef BUILD_K3BSETUP
-    const QString k3bSetupSolutionText = i18n("Click \"Modify Permissions...\" to solve this problem.");
-#else
-    const QString k3bSetupSolutionText = QString();
-#endif
+    bool showDeviceSettingsButton = false;
+    bool showBinSettingsButton = false;
 
     if( k3bcore->deviceManager()->allDevices().isEmpty() ) {
         problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL,
@@ -234,18 +228,18 @@ void K3b::SystemProblemDialog::checkSystem( QWidget* parent, NotificationLevel l
                 k3bcore->externalBinManager()->binObject( "cdrecord" )->version() < K3b::Version( 2, 1, 1, "a05" ) &&
                 !k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "wodim" ) ) {
                 if( k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "suidroot" ) ) {
-                    showK3bSetupButton = true;
+                    showBinSettingsButton = true;
                     problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL,
                                                          i18n("%1 will be run with root privileges on kernel >= 2.6.8",QString("cdrecord <= 2.01.01a05")),
                                                          i18n("Since Linux kernel 2.6.8 %1 will not work when run suid "
                                                               "root for security reasons anymore.",
                                                          QLatin1String( "cdrecord <= 2.01.01a05") ),
-                                                         k3bSetupSolutionText ) );
+                                                         i18n("Click \"Configure K3b...\" to solve this problem.") ) );
                 }
             }
 #ifdef CDRECORD_SUID_ROOT_CHECK
             else if( !k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "suidroot" ) && getuid() != 0 ) { // not root
-                showK3bSetupButton = true;
+                showBinSettingsButton = true;
                 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL,
                                                      i18n("%1 will be run without root privileges",QString("cdrecord")),
                                                      i18n("It is highly recommended to configure cdrecord "
@@ -254,7 +248,7 @@ void K3b::SystemProblemDialog::checkSystem( QWidget* parent, NotificationLevel l
                                                           "stability of the burning process. As well as this, "
                                                           "it allows the size of the burning buffer to be changed, "
                                                           "and a lot of user problems can be solved this way."),
-                                                     k3bSetupSolutionText ) );
+                                                     i18n("Click \"Configure K3b...\" to solve this problem.") ) );
             }
 #endif // CDRECORD_SUID_ROOT_CHECK
 #endif
@@ -270,13 +264,13 @@ void K3b::SystemProblemDialog::checkSystem( QWidget* parent, NotificationLevel l
 #ifdef Q_OS_LINUX
 #ifdef CDRECORD_SUID_ROOT_CHECK
             if( !k3bcore->externalBinManager()->binObject( "cdrdao" )->hasFeature( "suidroot" ) && getuid() != 0 ) {
-                showK3bSetupButton = true;
+                showBinSettingsButton = true;
                 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL,
                                                      i18n("%1 will be run without root privileges",QString("cdrdao")),
                                                      i18n("It is highly recommended to configure cdrdao "
                                                           "to run with root privileges to increase the "
                                                           "overall stability of the burning process."),
-                                                     k3bSetupSolutionText ) );
+                                                     i18n("Click \"Configure K3b...\" to solve this problem.") ) );
             }
 #endif // CDRECORD_SUID_ROOT_CHECK
 #endif
@@ -319,14 +313,14 @@ void K3b::SystemProblemDialog::checkSystem( QWidget* parent, NotificationLevel l
             }
 //            // for now we ignore the suid root bit becasue of the memorylocked issue
 //            else if( !k3bcore->externalBinManager()->binObject( "growisofs" )->hasFeature( "suidroot" ) ) {
-//                showK3bSetupButton = true;
+//                showBinSettingsButton = true;
 //                problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL,
 //                                                     i18n("%1 will be run without root privileges","growisofs"),
 //                                                     i18n("It is highly recommended to configure growisofs "
 //                                                          "to run with root privileges. Only then growisofs "
 //                                                          "runs with high priority which increases the overall "
 //                                                          "stability of the burning process."),
-//                                                     k3bSetupSolutionText ) );
+//                                                     i18n("Click \"Configure K3b...\" to solve this problem.") ) );
 //            }
         }
 
@@ -462,7 +456,7 @@ void K3b::SystemProblemDialog::checkSystem( QWidget* parent, NotificationLevel l
         K3b::Device::Device* dev = (*it);
 #ifndef Q_OS_WIN32
         if( !QFileInfo( dev->blockDeviceName() ).isWritable() ) {
-            showK3bSetupButton = true;
+            showDeviceSettingsButton = true;
             problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL,
                                                i18n("No write access to device %1",dev->blockDeviceName()),
                                                i18n("K3b needs write access to all the devices to perform certain tasks. "
@@ -552,16 +546,14 @@ void K3b::SystemProblemDialog::checkSystem( QWidget* parent, NotificationLevel l
     // the kdelibs refuse it.
     //
     if( ::getuid() == 0 ) {
-        showK3bSetupButton = true;
+        showDeviceSettingsButton = true;
         problems.append( K3b::SystemProblem( K3b::SystemProblem::WARNING,
                                            i18n("Running K3b as root user"),
                                            i18n("It is not recommended to run K3b under the root user account. "
                                                 "This introduces unnecessary security risks."),
                                            i18n("Run K3b from a proper user account and setup the device and "
                                                 "external tool permissions appropriately.")
-#ifdef BUILD_K3BSETUP
-                                           + ' ' + i18n("The latter can be done via \"Modify Permissions...\".")
-#endif
+                                           + ' ' + i18n("The latter can be done via \"Configure K3b...\".")
                                            ) );
     }
 
@@ -599,7 +591,7 @@ void K3b::SystemProblemDialog::checkSystem( QWidget* parent, NotificationLevel l
         static K3b::SystemProblemDialog* s_openDlg = 0;
         if( s_openDlg )
             s_openDlg->close();
-        K3b::SystemProblemDialog dlg( problems, showK3bSetupButton, parent );
+        K3b::SystemProblemDialog dlg( problems, showDeviceSettingsButton, showBinSettingsButton, parent );
         s_openDlg = &dlg;
         dlg.exec();
         s_openDlg = 0;
@@ -610,12 +602,15 @@ void K3b::SystemProblemDialog::checkSystem( QWidget* parent, NotificationLevel l
     cfg.writeEntry( "Last system check version", QString(k3bcore->version()) );
 }
 
-void K3b::SystemProblemDialog::slotK3bSetup()
+void K3b::SystemProblemDialog::slotShowDeviceSettings()
+{
+    k3bappcore->k3bMainWindow()->showOptionDialog( OptionDialog::Devices );
+}
+
+
+void K3b::SystemProblemDialog::slotShowBinSettings()
 {
-    QStringList args;
-    args << "k3bsetup" << "--lang" << KGlobal::locale()->language();
-    if( !KProcess::startDetached( K3b::findExe("kcmshell4"), args ) )
-        KMessageBox::error( 0, i18n("Unable to start K3b::Setup.") );
+    k3bappcore->k3bMainWindow()->showOptionDialog( OptionDialog::Programs );
 }
 
 
diff --git a/src/k3bsystemproblemdialog.h b/src/k3bsystemproblemdialog.h
index 512fcf3..6f340c8 100644
--- a/src/k3bsystemproblemdialog.h
+++ b/src/k3bsystemproblemdialog.h
@@ -85,11 +85,13 @@ namespace K3b {
         void closeEvent( QCloseEvent* );
 
     private Q_SLOTS:
-        void slotK3bSetup();
+        void slotShowDeviceSettings();
+        void slotShowBinSettings();
 
     private:
         SystemProblemDialog( const QList<SystemProblem>& problems,
-                             bool showK3bSetupButton,
+                             bool showDeviceSettingsButton,
+                             bool showBinSettingsButton,
                              QWidget* parent = 0);
         static int dmaActivated( Device::Device* );
 #ifndef Q_OS_WIN32
diff --git a/src/k3bui.rc b/src/k3bui.rc
index cd70a8f..8821ba3 100644
--- a/src/k3bui.rc
+++ b/src/k3bui.rc
@@ -29,7 +29,6 @@
             <Action name="view_document_header" />
         </Menu>
         <Action name="view_audio_player" append="show_merge" />
-        <Action name="settings_k3bsetup" append="configure_merge" />
     </Menu>
 
     <Menu name="help"><text>&Help</text>
diff --git a/src/option/k3bdeviceoptiontab.cpp b/src/option/k3bdeviceoptiontab.cpp
index ca40e76..d378232 100644
--- a/src/option/k3bdeviceoptiontab.cpp
+++ b/src/option/k3bdeviceoptiontab.cpp
@@ -1,6 +1,7 @@
 /*
  *
  * Copyright (C) 2003-2009 Sebastian Trueg <trueg at k3b.org>
+ * Copyright (C) 2011 Michal Malek <michalm at jabster.pl>
  *
  * This file is part of the K3b project.
  * Copyright (C) 1998-2009 Sebastian Trueg <trueg at k3b.org>
@@ -21,39 +22,21 @@
 #include <KConfigGroup>
 #include <KGlobal>
 #include <KLocale>
-#include <KMessageBox>
-#include <KProcess>
 
-#include <QApplication>
-#include <QCursor>
-#include <QGridLayout>
-#include <QLabel>
-#include <QString>
+#include <QtGui/QApplication>
+#include <QtGui/QCursor>
+#include <QtGui/QVBoxLayout>
 
 
 K3b::DeviceOptionTab::DeviceOptionTab( QWidget* parent )
     : QWidget( parent )
 {
-    QGridLayout* frameLayout = new QGridLayout( this );
-    frameLayout->setContentsMargins( 0, 0, 0, 0 );
-
-
-    // Info Label
-    // ------------------------------------------------
-    m_labelDevicesInfo = new QLabel( this );
-    m_labelDevicesInfo->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
-    m_labelDevicesInfo->setText( "<p>" + i18n( "K3b tries to detect all your devices properly. "
-                                               "If K3b is unable to detect your drive, you need to modify "
-                                               "their permissions to give K3b write access to all devices." ) );
-    m_labelDevicesInfo->setWordWrap(true);
-    // ------------------------------------------------
-
     m_deviceWidget = new K3b::DeviceWidget( k3bcore->deviceManager(), this );
 
-    frameLayout->addWidget( m_labelDevicesInfo, 0, 0 );
-    frameLayout->addWidget( m_deviceWidget, 1, 0 );
+    QVBoxLayout* layout = new QVBoxLayout( this );
+    layout->setContentsMargins( 0, 0, 0, 0 );
+    layout->addWidget( m_deviceWidget );
 
-    connect( m_deviceWidget, SIGNAL(modifyPermissionsButtonClicked()), this, SLOT(slotModifyPermissionsButtonClicked()) );
     connect( m_deviceWidget, SIGNAL(refreshButtonClicked()), this, SLOT(slotRefreshButtonClicked()) );
 }
 
@@ -77,15 +60,6 @@ void K3b::DeviceOptionTab::saveDevices()
 }
 
 
-void K3b::DeviceOptionTab::slotModifyPermissionsButtonClicked()
-{
-    QStringList args;
-    args << "k3bsetup" << "--lang" << KGlobal::locale()->language();
-    if( !KProcess::startDetached( K3b::findExe("kcmshell4"), args ) )
-        KMessageBox::error( this, i18n("Unable to start K3b::Setup.") );
-}
-
-
 void K3b::DeviceOptionTab::slotRefreshButtonClicked()
 {
     QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
diff --git a/src/option/k3bdeviceoptiontab.h b/src/option/k3bdeviceoptiontab.h
index 09b0389..58729bf 100644
--- a/src/option/k3bdeviceoptiontab.h
+++ b/src/option/k3bdeviceoptiontab.h
@@ -1,6 +1,7 @@
 /*
  *
  * Copyright (C) 2003 Sebastian Trueg <trueg at k3b.org>
+ * Copyright (C) 2011 Michal Malek <michalm at jabster.pl>
  *
  * This file is part of the K3b project.
  * Copyright (C) 1998-2007 Sebastian Trueg <trueg at k3b.org>
@@ -18,8 +19,6 @@
 
 #include <QWidget>
 
-class QLabel;
-
 namespace K3b {
     class DeviceWidget;
 
@@ -35,11 +34,9 @@ namespace K3b {
         void saveDevices();
 
     private Q_SLOTS:
-        void slotModifyPermissionsButtonClicked();
         void slotRefreshButtonClicked();
 
     private:
-        QLabel* m_labelDevicesInfo;
         DeviceWidget* m_deviceWidget;
     };
 }
diff --git a/src/option/k3bdevicewidget.cpp b/src/option/k3bdevicewidget.cpp
index d2b7129..754c367 100644
--- a/src/option/k3bdevicewidget.cpp
+++ b/src/option/k3bdevicewidget.cpp
@@ -1,7 +1,7 @@
 /*
  *
  * Copyright (C) 2003-2008 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C)      2010 Michal Malek <michalm at jabster.pl>
+ * Copyright (C) 2010-2011 Michal Malek <michalm at jabster.pl>
  *
  * This file is part of the K3b project.
  * Copyright (C) 1998-2008 Sebastian Trueg <trueg at k3b.org>
@@ -18,18 +18,21 @@
 #include "k3bdevicemanager.h"
 #include "k3bdevice.h"
 #include "k3bdeviceglobals.h"
-#include "config-k3b.h"
 
+#include <KAction>
+#include <KAuth/Action>
 #include <KConfig>
 #include <KIcon>
 #include <KLocale>
 #include <KStandardDirs>
+#include <KMessageWidget>
 #include <kio/global.h>
 
 #include <QColor>
-#include <QHBoxLayout>
+#include <QFileInfo>
 #include <QGridLayout>
 #include <QGroupBox>
+#include <QHBoxLayout>
 #include <QHeaderView>
 #include <QLayout>
 #include <QList>
@@ -40,6 +43,8 @@
 #include <QVariant>
 #include <QVBoxLayout>
 
+#include <grp.h>
+#include <unistd.h>
 
 
 K3b::DeviceWidget::DeviceWidget( K3b::Device::DeviceManager* manager, QWidget *parent )
@@ -48,32 +53,25 @@ K3b::DeviceWidget::DeviceWidget( K3b::Device::DeviceManager* manager, QWidget *p
       m_writerParentViewItem( 0 ),
       m_readerParentViewItem( 0 )
 {
-    QVBoxLayout* frameLayout = new QVBoxLayout( this );
-    frameLayout->setContentsMargins( 0, 0, 0, 0 );
-
+    // message widget
+    m_messageWidget = new KMessageWidget( this );
+    m_messageWidget->hide();
+    m_messageWidget->setWordWrap( true );
+    m_addToGroupAction = new KAction( KIcon("dialog-password"), QString(), this );
 
     // buttons
     // ------------------------------------------------
-    QPushButton* modifyPermissions = new QPushButton( i18n( "Modify Permissions..." ), this );
-    QPushButton* buttonRefreshDevices = new QPushButton( i18n( "Refresh" ), this );
+    QPushButton* buttonRefreshDevices = new QPushButton( KIcon( "view-refresh" ), i18n( "Refresh" ), this );
     buttonRefreshDevices->setToolTip( i18n( "Rescan the devices" ) );
     QHBoxLayout* refreshButtonGrid = new QHBoxLayout;
     refreshButtonGrid->setContentsMargins( 0, 0, 0, 0 );
     refreshButtonGrid->addStretch();
-    refreshButtonGrid->addWidget( modifyPermissions );
     refreshButtonGrid->addWidget( buttonRefreshDevices );
     // ------------------------------------------------
 
-#ifndef BUILD_K3BSETUP
-    modifyPermissions->setVisible( false );
-#endif
-
-    // Devices Box
+    // Devices view
     // ------------------------------------------------
-    QGroupBox* groupDevices = new QGroupBox( i18n( "CD/DVD/BD Drives" ), this );
-    QVBoxLayout* groupDevicesLayout = new QVBoxLayout( groupDevices );
-
-    m_viewDevices = new QTreeWidget( groupDevices );
+    m_viewDevices = new QTreeWidget( this );
     m_viewDevices->setAllColumnsShowFocus( true );
     m_viewDevices->setHeaderHidden( true );
     m_viewDevices->setColumnCount( 2 );
@@ -83,20 +81,20 @@ K3b::DeviceWidget::DeviceWidget( K3b::Device::DeviceManager* manager, QWidget *p
     m_viewDevices->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
     m_viewDevices->setFocusPolicy( Qt::NoFocus );
     m_viewDevices->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
-
-    groupDevicesLayout->addWidget( m_viewDevices );
     // ------------------------------------------------
 
-
-    frameLayout->addWidget( groupDevices );
-    frameLayout->addLayout( refreshButtonGrid );
+    QVBoxLayout* frameLayout = new QVBoxLayout( this );
+    frameLayout->setContentsMargins( 0, 0, 0, 0 );
+    frameLayout->addWidget( m_messageWidget, 0 );
+    frameLayout->addWidget( m_viewDevices, 1 );
+    frameLayout->addLayout( refreshButtonGrid, 0 );
     // ------------------------------------------------
 
     // connections
     // ------------------------------------------------
-    connect( modifyPermissions, SIGNAL(clicked()), this, SIGNAL(modifyPermissionsButtonClicked()) );
-    connect( buttonRefreshDevices, SIGNAL(clicked()), this, SIGNAL(refreshButtonClicked()) );
-    connect( m_deviceManager, SIGNAL(changed()), this, SLOT(init()) );
+    connect( buttonRefreshDevices, SIGNAL(clicked()), SIGNAL(refreshButtonClicked()) );
+    connect( m_deviceManager, SIGNAL(changed()), SLOT(init()) );
+    connect( m_addToGroupAction, SIGNAL(triggered(bool)), SLOT(addUserToGroup()) );
     // ------------------------------------------------
 }
 
@@ -224,6 +222,60 @@ void K3b::DeviceWidget::updateDeviceListViews()
     }
 
     m_viewDevices->expandAll();
+
+    // Show warning message if the current user does not belong to
+    // the group device belongs to
+    QList<Device::Device*> devices = m_deviceManager->allDevices();
+    if( !devices.empty() ) {
+        QFileInfo fileInfo( devices.front()->blockDeviceName() );
+        m_deviceGroup = fileInfo.group();
+
+        if( m_deviceGroup != "root" ) {
+            QVector<gid_t> gids(::getgroups(0, 0));
+            ::getgroups(gids.size(), gids.data());
+
+            QSet<QString> groupNames;
+            Q_FOREACH( gid_t gid, gids ) {
+                if( ::group* g = ::getgrgid( gid ) ) {
+                    groupNames.insert( QString::fromLocal8Bit( g->gr_name ) );
+                }
+            }
+
+            if (!groupNames.contains(m_deviceGroup)) {
+                m_messageWidget->setMessageType(KMessageWidget::Warning);
+                m_messageWidget->setText(i18n("In order to give K3b full access to the writer device the current user needs be added to a group <em>%1</em>.", m_deviceGroup));
+                m_messageWidget->addAction(m_addToGroupAction);
+                m_messageWidget->animatedShow();
+                m_addToGroupAction->setText(i18n("Add"));
+            }
+        }
+    }
+}
+
+void K3b::DeviceWidget::addUserToGroup()
+{
+    QVariantMap args;
+    args["groupName"] = m_deviceGroup;
+    args["userName"] = QString::fromLocal8Bit(::cuserid(NULL));
+
+    KAuth::Action action("org.kde.k3b.addtogroup");
+    action.setHelperID("org.kde.k3b");
+    action.setParentWidget(this);
+    action.setArguments(args);
+
+    KAuth::ActionReply reply = action.execute();
+    if (reply.succeeded()) {
+        m_messageWidget->removeAction(m_addToGroupAction);
+        m_messageWidget->setMessageType(KMessageWidget::Information);
+        m_messageWidget->setText(i18n("Please relogin to apply the changes."));
+    } else if (reply.type() != KAuth::ActionReply::KAuthError ||
+               (reply.errorCode() != KAuth::ActionReply::NoError &&
+                reply.errorCode() != KAuth::ActionReply::AuthorizationDenied &&
+                reply.errorCode() != KAuth::ActionReply::UserCancelled)) {
+        m_messageWidget->setMessageType(KMessageWidget::Error);
+        m_messageWidget->setText(i18n("Unable to execute the action: %1", reply.errorDescription()));
+        m_addToGroupAction->setText(i18n("Retry"));
+    }
 }
 
 #include "k3bdevicewidget.moc"
diff --git a/src/option/k3bdevicewidget.h b/src/option/k3bdevicewidget.h
index 88b4d93..61b295e 100644
--- a/src/option/k3bdevicewidget.h
+++ b/src/option/k3bdevicewidget.h
@@ -1,6 +1,7 @@
 /*
  *
  * Copyright (C) 2003-2009 Sebastian Trueg <trueg at k3b.org>
+ * Copyright (C) 2011 Michal Malek <michalm at jabster.pl>
  *
  * This file is part of the K3b project.
  * Copyright (C) 1998-2009 Sebastian Trueg <trueg at k3b.org>
@@ -18,6 +19,8 @@
 
 #include <QWidget>
 
+class KMessageWidget;
+class QAction;
 class QTreeWidget;
 class QTreeWidgetItem;
 
@@ -39,11 +42,11 @@ namespace K3b {
         void init();
 
     Q_SIGNALS:
-        void modifyPermissionsButtonClicked();
         void refreshButtonClicked();
 
     private Q_SLOTS:
         void updateDeviceListViews();
+        void addUserToGroup();
 
     private:
         Device::DeviceManager* m_deviceManager;
@@ -52,6 +55,9 @@ namespace K3b {
         QTreeWidgetItem* m_readerParentViewItem;
 
         QTreeWidget* m_viewDevices;
+        KMessageWidget* m_messageWidget;
+        QAction* m_addToGroupAction;
+        QString m_deviceGroup;
     };
 }
 
diff --git a/k3bsetup/k3bsetupprogramsmodel.cpp b/src/option/k3bexternalbinpermissionmodel.cpp
similarity index 68%
rename from k3bsetup/k3bsetupprogramsmodel.cpp
rename to src/option/k3bexternalbinpermissionmodel.cpp
index a64d150..803e162 100644
--- a/k3bsetup/k3bsetupprogramsmodel.cpp
+++ b/src/option/k3bexternalbinpermissionmodel.cpp
@@ -14,13 +14,11 @@
  * See the file "COPYING" for the exact licensing terms.
  */
 
-#include "k3bsetupprogramsmodel.h"
+#include "k3bexternalbinpermissionmodel.h"
 #include "k3bexternalbinmanager.h"
 #include "k3bdefaultexternalprograms.h"
 #include "k3bglobals.h"
 
-#include <KConfig>
-#include <KConfigGroup>
 #include <KDebug>
 #include <KLocale>
 
@@ -69,12 +67,12 @@ bool shouldRunSuidRoot( const K3b::ExternalBin* bin )
 } // namespace
 
 namespace K3b {
-namespace Setup {
 
-class ProgramsModel::Private
+class ExternalBinPermissionModel::Private
 {
 public:
-    ExternalBinManager* externalBinManager;
+    explicit Private(ExternalBinManager const& ebm) : externalBinManager(ebm) {}
+    ExternalBinManager const& externalBinManager;
     QString burningGroup;
     QList<const ExternalBin*> programs;
     QSet<const ExternalBin*> selectedPrograms;
@@ -87,18 +85,22 @@ public:
 };
 
 
-void ProgramsModel::Private::buildProgramList()
+void ExternalBinPermissionModel::Private::buildProgramList()
 {
-    externalBinManager->search();
     programs.clear();
-    const QMap<QString, ExternalProgram*>& map = externalBinManager->programs();
+    const QMap<QString, ExternalProgram*>& map = externalBinManager.programs();
     for( QMap<QString, ExternalProgram*>::const_iterator it = map.constBegin(); it != map.constEnd(); ++it ) {
-        programs += it.value()->bins();
+        if (it.key() == "cdrecord" ||
+            it.key() == "cdrdao" ||
+            it.key() == "growisofs") {
+            programs += it.value()->bins();
+        }
     }
+    selectedPrograms = programs.toSet();
 }
 
 
-bool ProgramsModel::Private::getProgramInfo( const ExternalBin* program,
+bool ExternalBinPermissionModel::Private::getProgramInfo( const ExternalBin* program,
                                                   QString& owner, QString& group, QString& wantedGroup,
                                                   int& perm, int& wantedPerm ) const
 {
@@ -111,19 +113,19 @@ bool ProgramsModel::Private::getProgramInfo( const ExternalBin* program,
         group = fi.group();
         perm = s.st_mode & 0007777;
 
-        if( !burningGroup.isEmpty() )
+        if( !burningGroup.isEmpty() && burningGroup != "root" )
             wantedGroup = burningGroup;
         else
             wantedGroup = "root";
 
         if( shouldRunSuidRoot( program ) ) {
-            if( !burningGroup.isEmpty() )
+            if( wantedGroup != "root" )
                 wantedPerm = 0004710;
             else
                 wantedPerm = 0004711;
         }
         else {
-            if( !burningGroup.isEmpty() )
+            if( wantedGroup != "root" )
                 wantedPerm = 0000750;
             else
                 wantedPerm = 0000755;
@@ -132,13 +134,13 @@ bool ProgramsModel::Private::getProgramInfo( const ExternalBin* program,
         return true;
     }
     else {
-        kDebug() << "(K3bSetup) unable to stat " << program->path();
+        kDebug() << "(ExternalBinPermissionModel) unable to stat " << program->path();
         return false;
     }
 }
 
 
-bool ProgramsModel::Private::needChangePermissions( const ExternalBin* program ) const
+bool ExternalBinPermissionModel::Private::needChangePermissions( const ExternalBin* program ) const
 {
     QString owner, group, wantedGroup;
     int perm, wantedPerm;
@@ -150,74 +152,52 @@ bool ProgramsModel::Private::needChangePermissions( const ExternalBin* program )
 }
 
 
-ProgramsModel::ProgramsModel( QObject* parent )
+ExternalBinPermissionModel::ExternalBinPermissionModel(ExternalBinManager const& externalBinManager, QObject* parent)
 :
     QAbstractItemModel( parent ),
-    d( new Private )
+    d( new Private( externalBinManager ) )
 {
-    d->externalBinManager = new ExternalBinManager( this );
-    // these are the only programs that need special permissions
-    d->externalBinManager->addProgram( new CdrdaoProgram() );
-    d->externalBinManager->addProgram( new CdrecordProgram() );
-    d->externalBinManager->addProgram( new GrowisofsProgram() );
     d->buildProgramList();
 }
 
 
-ProgramsModel::~ProgramsModel()
+ExternalBinPermissionModel::~ExternalBinPermissionModel()
 {
     delete d;
 }
 
 
-void ProgramsModel::load( const KConfig& config )
-{
-    d->selectedPrograms.clear();
-    d->externalBinManager->readConfig( config.group( "External Programs" ) );
-    d->buildProgramList();
-    reset();
-}
-
-
-void ProgramsModel::save( KConfig& config ) const
-{
-    d->externalBinManager->saveConfig( config.group( "External Programs" ) );
-}
-
-
-void ProgramsModel::defaults()
-{
-    d->selectedPrograms.clear();
-    d->buildProgramList();
-    reset();
-}
-
-
-QList<ProgramItem> ProgramsModel::selectedPrograms() const
+QList<HelperProgramItem> ExternalBinPermissionModel::selectedPrograms() const
 {
-    QList<ProgramItem> selectedPrograms;
+    QList<HelperProgramItem> selectedPrograms;
     Q_FOREACH( const ExternalBin* program, d->selectedPrograms )
     {
         if( d->needChangePermissions( program ) )
-            selectedPrograms << ProgramItem( program->path(), shouldRunSuidRoot( program ) );
+            selectedPrograms << HelperProgramItem( program->path(), shouldRunSuidRoot( program ) );
     }
     return selectedPrograms;
 }
 
 
-bool ProgramsModel::changesNeeded() const
+bool ExternalBinPermissionModel::changesNeeded() const
 {
     return !selectedPrograms().isEmpty();
 }
 
 
-QStringList ProgramsModel::searchPaths() const
+QStringList ExternalBinPermissionModel::searchPaths() const
 {
-    return d->externalBinManager->searchPath();
+    return d->externalBinManager.searchPath();
 }
 
 
-const ExternalBin* ProgramsModel::programForIndex( const QModelIndex& index ) const
+const QString& ExternalBinPermissionModel::burningGroup() const
+{
+    return d->burningGroup;
+}
+
+
+const ExternalBin* ExternalBinPermissionModel::programForIndex( const QModelIndex& index ) const
 {
     if( index.isValid() )
         return static_cast<const ExternalBin*>( index.internalPointer() );
@@ -226,7 +206,7 @@ const ExternalBin* ProgramsModel::programForIndex( const QModelIndex& index ) co
 }
 
 
-QModelIndex ProgramsModel::indexForProgram( const ExternalBin* program ) const
+QModelIndex ExternalBinPermissionModel::indexForProgram( const ExternalBin* program ) const
 {
     if( program != 0 && !d->programs.isEmpty() ) {
         int row = d->programs.indexOf( program );
@@ -237,29 +217,21 @@ QModelIndex ProgramsModel::indexForProgram( const ExternalBin* program ) const
 }
 
 
-QVariant ProgramsModel::data( const QModelIndex& index, int role ) const
+QVariant ExternalBinPermissionModel::data( const QModelIndex& index, int role ) const
 {
     if( const ExternalBin* program = programForIndex( index ) ) {
         if( role == Qt::DisplayRole ) {
-            if( index.column() == 0 ) {
-                return program->name();
-            }
-            else if( index.column() == 1 ) {
-                return program->version().toString();
-            }
-            else if( index.column() == 2 ) {
+            if( index.column() == ProgramColumn ) {
                 return program->path();
-            }
-            else {
+            } else {
                 QString owner, group, wantedGroup;
                 int perm, wantedPerm;
 
                 if( d->getProgramInfo( program, owner, group, wantedGroup, perm, wantedPerm ) ) {
 
-                    if( index.column() == 3 ) {
+                    if( index.column() == PermissionsColumn ) {
                         return QString(QString::number( perm, 8 ).rightJustified( 4, '0' ) + " " + owner + "." + group);
-                    }
-                    else if ( index.column() == 4 ) {
+                    } else if ( index.column() == NewPermissionsColumn ) {
                         if( perm != wantedPerm || owner != "root" || group != wantedGroup )
                             return QString("%1 root.%2").arg(wantedPerm,0,8).arg(wantedGroup);
                         else
@@ -268,7 +240,7 @@ QVariant ProgramsModel::data( const QModelIndex& index, int role ) const
                 }
             }
         }
-        else if( role == Qt::CheckStateRole && index.column() == 0 && d->needChangePermissions( program ) ) {
+        else if( role == Qt::CheckStateRole && index.column() == ProgramColumn && d->needChangePermissions( program ) ) {
             if( d->selectedPrograms.contains( program ) )
                 return Qt::Checked;
             else
@@ -279,7 +251,7 @@ QVariant ProgramsModel::data( const QModelIndex& index, int role ) const
 }
 
 
-bool ProgramsModel::setData( const QModelIndex& index, const QVariant& value, int role )
+bool ExternalBinPermissionModel::setData( const QModelIndex& index, const QVariant& value, int role )
 {
     if( role == Qt::CheckStateRole ) {
         if( const ExternalBin* program = programForIndex( index ) ) {
@@ -299,11 +271,11 @@ bool ProgramsModel::setData( const QModelIndex& index, const QVariant& value, in
 }
 
 
-Qt::ItemFlags ProgramsModel::flags( const QModelIndex& index ) const
+Qt::ItemFlags ExternalBinPermissionModel::flags( const QModelIndex& index ) const
 {
     if( const ExternalBin* program = programForIndex( index ) )
     {
-        if( index.column() == 0 && d->needChangePermissions( program ) )
+        if( index.column() == ProgramColumn && d->needChangePermissions( program ) )
             return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
         else
             return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
@@ -313,16 +285,14 @@ Qt::ItemFlags ProgramsModel::flags( const QModelIndex& index ) const
 }
 
 
-QVariant ProgramsModel::headerData( int section, Qt::Orientation orientation, int role ) const
+QVariant ExternalBinPermissionModel::headerData( int section, Qt::Orientation orientation, int role ) const
 {
     if( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
         switch( section )
         {
-            case 0: return i18n( "Program" );
-            case 1: return i18n( "Version" );
-            case 2: return i18n( "Path" );
-            case 3: return i18n( "Permissions" );
-            case 4: return i18n( "New permissions" );
+            case ProgramColumn: return i18n( "Program" );
+            case PermissionsColumn: return i18n( "Permissions" );
+            case NewPermissionsColumn: return i18n( "New permissions" );
             default: return QVariant();
         }
     }
@@ -331,7 +301,7 @@ QVariant ProgramsModel::headerData( int section, Qt::Orientation orientation, in
 }
 
 
-QModelIndex ProgramsModel::index( int row, int column, const QModelIndex& parent ) const
+QModelIndex ExternalBinPermissionModel::index( int row, int column, const QModelIndex& parent ) const
 {
     if( hasIndex(row, column, parent) && !parent.isValid() ) {
         const ExternalBin* program = d->programs.at( row );
@@ -345,14 +315,14 @@ QModelIndex ProgramsModel::index( int row, int column, const QModelIndex& parent
 }
 
 
-QModelIndex ProgramsModel::parent( const QModelIndex& index ) const
+QModelIndex ExternalBinPermissionModel::parent( const QModelIndex& index ) const
 {
     Q_UNUSED( index );
     return QModelIndex();
 }
 
 
-int ProgramsModel::rowCount( const QModelIndex& parent ) const
+int ExternalBinPermissionModel::rowCount( const QModelIndex& parent ) const
 {
     if( !parent.isValid() )
         return d->programs.size();
@@ -361,14 +331,23 @@ int ProgramsModel::rowCount( const QModelIndex& parent ) const
 }
 
 
-int ProgramsModel::columnCount( const QModelIndex& parent ) const
+int ExternalBinPermissionModel::columnCount( const QModelIndex& parent ) const
 {
     Q_UNUSED( parent );
-    return 5;
+    return NumColumns;
 }
 
 
-void ProgramsModel::setBurningGroup( const QString& burningGroup )
+QModelIndex ExternalBinPermissionModel::buddy( const QModelIndex& index ) const
+{
+    if( programForIndex( index ) != 0 )
+        return ExternalBinPermissionModel::index( index.row(), ProgramColumn, index.parent() );
+    else
+        return index;
+}
+
+
+void ExternalBinPermissionModel::setBurningGroup( const QString& burningGroup )
 {
     if( burningGroup != d->burningGroup ) {
         d->burningGroup = burningGroup;
@@ -387,22 +366,13 @@ void ProgramsModel::setBurningGroup( const QString& burningGroup )
     }
 }
 
-void ProgramsModel::setSearchPaths( const QStringList& searchPaths )
-{
-    if( searchPaths != d->externalBinManager->searchPath() ) {
-        d->externalBinManager->setSearchPath( searchPaths );
-        update();
-    }
-}
-
-void ProgramsModel::update()
+void ExternalBinPermissionModel::update()
 {
     d->buildProgramList();
     d->selectedPrograms.intersect( d->programs.toSet() );
     reset();
 }
 
-} // namespace Setup
 } // namespace K3b
 
-#include "k3bsetupprogramsmodel.moc"
+#include "k3bexternalbinpermissionmodel.moc"
diff --git a/src/option/k3bexternalbinpermissionmodel.h b/src/option/k3bexternalbinpermissionmodel.h
new file mode 100644
index 0000000..dc67a5a
--- /dev/null
+++ b/src/option/k3bexternalbinpermissionmodel.h
@@ -0,0 +1,75 @@
+/*
+ *
+ * Copyright (C) 2003-2009 Sebastian Trueg <trueg at k3b.org>
+ * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2009 Sebastian Trueg <trueg at k3b.org>
+ * Copyright (C) 2009 Michal Malek <michalm at jabster.pl>
+ *
+ * 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.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef K3BEXTERNALBINPERMISSIONMODEL_H
+#define K3BEXTERNALBINPERMISSIONMODEL_H
+
+#include "k3bhelperprogramitem.h"
+#include <QAbstractItemModel>
+#include <QList>
+#include <QStringList>
+
+namespace K3b {
+
+    class ExternalBin;
+    class ExternalBinManager;
+
+    class ExternalBinPermissionModel : public QAbstractItemModel
+    {
+        Q_OBJECT
+
+    public:
+        enum Columns {
+            ProgramColumn,
+            PermissionsColumn,
+            NewPermissionsColumn,
+            NumColumns
+        };
+
+    public:
+        ExternalBinPermissionModel(ExternalBinManager const& externalBinManager, QObject* parent = 0);
+        ~ExternalBinPermissionModel();
+
+        QList<HelperProgramItem> selectedPrograms() const;
+        bool changesNeeded() const;
+        QStringList searchPaths() const;
+        const QString& burningGroup() const;
+
+        const ExternalBin* programForIndex( const QModelIndex& index ) const;
+        QModelIndex indexForProgram( const ExternalBin* program ) const;
+
+        virtual QVariant data( const QModelIndex& index, int role ) const;
+        virtual bool setData( const QModelIndex& index, const QVariant& value, int role );
+        virtual Qt::ItemFlags flags( const QModelIndex& index ) const;
+        virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
+        virtual QModelIndex index( int row, int column, const QModelIndex& parent = QModelIndex() ) const;
+        virtual QModelIndex parent( const QModelIndex& index ) const;
+        virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const;
+        virtual int columnCount( const QModelIndex& parent = QModelIndex() ) const;
+        virtual QModelIndex buddy( const QModelIndex& index ) const;
+
+    public Q_SLOTS:
+        void setBurningGroup( const QString& burningGroup );
+        void update();
+
+    private:
+        class Private;
+        Private* d;
+    };
+
+} // namespace K3b
+
+#endif // K3BEXTERNALBINPERMISSIONMODEL_H
diff --git a/src/option/k3bexternalbinwidget.cpp b/src/option/k3bexternalbinwidget.cpp
index 3a3e446..2eddcc3 100644
--- a/src/option/k3bexternalbinwidget.cpp
+++ b/src/option/k3bexternalbinwidget.cpp
@@ -17,6 +17,8 @@
 #include "k3bexternalbinmanager.h"
 #include "k3bexternalbinmodel.h"
 #include "k3bexternalbinparamsmodel.h"
+#include "k3bexternalbinpermissionmodel.h"
+#include "config-k3b.h"
 
 #include <QApplication>
 #include <QCursor>
@@ -33,13 +35,16 @@
 #include <QTreeView>
 #include <QVBoxLayout>
 
+#include <KAuth/Action>
 #include <KDebug>
 #include <KDialog>
 #include <KEditListBox>
 #include <KGlobalSettings>
 #include <KLocale>
+#include <KMessageBox>
+#include <KPushButton>
 
-
+#include <grp.h>
 
 
 
@@ -60,13 +65,12 @@ K3b::ExternalBinWidget::ExternalBinWidget( K3b::ExternalBinManager* manager, QWi
     mainGrid->setContentsMargins( 0, 0, 0, 0 );
 
     m_mainTabWidget = new QTabWidget( this );
-    m_rescanButton = new QPushButton( i18n("&Search"), this );
-    mainGrid->addWidget( m_mainTabWidget, 0, 0, 1, 2 );
-    mainGrid->addWidget( m_rescanButton, 1, 1 );
+    m_rescanButton = new QPushButton( KIcon( "view-refresh" ), i18n( "Refresh" ), this );
+    mainGrid->addWidget( m_mainTabWidget, 0, 0, 1, 3 );
+    mainGrid->addWidget( m_rescanButton, 1, 2 );
     mainGrid->setColumnStretch( 0, 1 );
     mainGrid->setRowStretch( 0, 1 );
 
-
     // setup program tab
     // ------------------------------------------------------------
     QWidget* programTab = new QWidget( m_mainTabWidget );
@@ -98,7 +102,7 @@ K3b::ExternalBinWidget::ExternalBinWidget( K3b::ExternalBinManager* manager, QWi
     m_parameterView->setAllColumnsShowFocus( true );
     m_parameterView->setRootIsDecorated( false );
     m_parameterView->setEditTriggers( QAbstractItemView::AllEditTriggers );
-    m_parameterView->header()->setResizeMode( ExternalBinParamsModel::ProgramColumn, QHeaderView::ResizeToContents );
+    m_parameterView->header()->setResizeMode( QHeaderView::ResizeToContents );
 
     QVBoxLayout* parametersTabLayout = new QVBoxLayout( parametersTab );
     parametersTabLayout->addWidget( parametersLabel );
@@ -107,6 +111,24 @@ K3b::ExternalBinWidget::ExternalBinWidget( K3b::ExternalBinManager* manager, QWi
     m_mainTabWidget->addTab( parametersTab, i18n("User Parameters") );
 
 
+    // setup permissions tab
+    // ------------------------------------------------------------
+    QWidget* permissionsTab = new QWidget( m_mainTabWidget );
+    QLabel* permissionsLabel = new QLabel( i18n("Check the programs whose permissions you want to be changed:"), permissionsTab );
+    m_permissionModel = new ExternalBinPermissionModel( *manager, permissionsTab );
+    m_permissionView = new QTreeView( permissionsTab );
+    m_permissionView->setModel( m_permissionModel );
+    m_permissionView->setAllColumnsShowFocus( true );
+    m_permissionView->setRootIsDecorated( false );
+    m_permissionView->header()->setResizeMode( ExternalBinPermissionModel::ProgramColumn, QHeaderView::ResizeToContents );
+    m_changePermissionsButton = new KPushButton( KIcon("dialog-password"), i18n( "Change Permissions..." ), this );
+    QVBoxLayout* permissionsTabLayout = new QVBoxLayout( permissionsTab );
+    permissionsTabLayout->addWidget( permissionsLabel );
+    permissionsTabLayout->addWidget( m_permissionView );
+    permissionsTabLayout->addWidget( m_changePermissionsButton );
+    m_mainTabWidget->addTab( permissionsTab, i18n("Permissions") );
+
+
     // setup search path tab
     // ------------------------------------------------------------
     QWidget* searchPathTab = new QWidget( m_mainTabWidget );
@@ -122,7 +144,23 @@ K3b::ExternalBinWidget::ExternalBinWidget( K3b::ExternalBinManager* manager, QWi
 
     m_mainTabWidget->addTab( searchPathTab, i18n("Search Path") );
 
+    connect( m_changePermissionsButton, SIGNAL(clicked()), SLOT(slotChangePermissions()) );
+    connect( m_permissionModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(slotPermissionModelChanged()) );
+    connect( m_permissionModel, SIGNAL(modelReset()), SLOT(slotPermissionModelChanged()) );
     connect( m_rescanButton, SIGNAL(clicked(bool)), this, SLOT(rescan()) );
+
+    qRegisterMetaType<HelperProgramItem>();
+    qRegisterMetaTypeStreamOperators<HelperProgramItem>("K3b::HelperProgramItem");
+
+    while (::group *g = ::getgrent()) {
+        const QString groupName = QString::fromLocal8Bit(g->gr_name);
+        if (groupName == "cdrom" ||
+            groupName == "optical" ||
+            groupName == "operator" ) {
+            m_permissionModel->setBurningGroup(groupName);
+        }
+    }
+    ::endgrent();
 }
 
 
@@ -166,4 +204,56 @@ void K3b::ExternalBinWidget::saveSearchPath()
     m_manager->setSearchPath( m_searchPathBox->items() );
 }
 
+
+void K3b::ExternalBinWidget::slotPermissionModelChanged()
+{
+    m_changePermissionsButton->setEnabled(m_permissionModel->changesNeeded());
+}
+
+
+void K3b::ExternalBinWidget::slotChangePermissions()
+{
+    KAuth::Action action("org.kde.k3b.updatepermissions");
+    action.setHelperID("org.kde.k3b");
+    action.setParentWidget(this);
+
+    QVariantMap args;
+
+    // Set burning group name as first argument
+    args["burningGroup"] = m_permissionModel->burningGroup();
+
+    // Set devices list as second argument
+    args["devices"] = QStringList();
+
+    // Set programs list as third argument
+    QVariantList programs;
+    Q_FOREACH(const HelperProgramItem& item, m_permissionModel->selectedPrograms()) {
+        programs << QVariant::fromValue(item);
+    }
+    args["programs"] = programs;
+
+    action.setArguments(args);
+
+    KAuth::ActionReply reply = action.execute();
+
+    if (reply.succeeded()) {
+        // Success!!
+        QStringList updated = reply.data()["updated"].toStringList();
+        QStringList failedToUpdate = reply.data()["failedToUpdate"].toStringList();
+        kDebug() << "Objects updated: " << updated;
+        kDebug() << "Objects failed to update: " << failedToUpdate;
+
+        if (!failedToUpdate.isEmpty()) {
+            KMessageBox::errorList(this, i18n("Following programs could not be updated:"), failedToUpdate);
+        }
+
+        m_permissionModel->update();
+    } else if (reply.type() != KAuth::ActionReply::KAuthError ||
+               (reply.errorCode() != KAuth::ActionReply::NoError &&
+                reply.errorCode() != KAuth::ActionReply::AuthorizationDenied &&
+                reply.errorCode() != KAuth::ActionReply::UserCancelled)) {
+        KMessageBox::error(this, i18n("Unable to execute the action: %1", reply.errorDescription()));
+    }
+}
+
 #include "k3bexternalbinwidget.moc"
diff --git a/src/option/k3bexternalbinwidget.h b/src/option/k3bexternalbinwidget.h
index bb1c5c0..f9c6dd4 100644
--- a/src/option/k3bexternalbinwidget.h
+++ b/src/option/k3bexternalbinwidget.h
@@ -1,7 +1,7 @@
 /*
  *
  * Copyright (C) 2003-2008 Sebastian Trueg <trueg at k3b.org>
- * Copyright (C) 2010 Michal Malek <michalm at jabster.pl>
+ * Copyright (C) 2010-2011 Michal Malek <michalm at jabster.pl>
  *
  * This file is part of the K3b project.
  * Copyright (C) 1998-2010 Sebastian Trueg <trueg at k3b.org>
@@ -33,6 +33,7 @@ namespace K3b {
     class ExternalBin;
     class ExternalBinModel;
     class ExternalBinParamsModel;
+    class ExternalBinPermissionModel;
 
     class ExternalBinWidget : public QWidget
     {
@@ -49,17 +50,22 @@ namespace K3b {
 
     private Q_SLOTS:
         void saveSearchPath();
+        void slotPermissionModelChanged();
+        void slotChangePermissions();
 
     private:
         ExternalBinManager* m_manager;
         ExternalBinModel* m_programModel;
         ExternalBinParamsModel* m_parameterModel;
+        ExternalBinPermissionModel* m_permissionModel;
 
         QTabWidget* m_mainTabWidget;
         QTreeView* m_programView;
         QTreeView* m_parameterView;
+        QTreeView* m_permissionView;
         KEditListBox* m_searchPathBox;
 
+        QPushButton* m_changePermissionsButton;
         QPushButton* m_rescanButton;
     };
 }
diff --git a/src/option/k3boptiondialog.cpp b/src/option/k3boptiondialog.cpp
index 41d39f7..174cd69 100644
--- a/src/option/k3boptiondialog.cpp
+++ b/src/option/k3boptiondialog.cpp
@@ -140,7 +140,7 @@ void K3b::OptionDialog::setupDevicePage()
 {
     m_deviceOptionTab = new K3b::DeviceOptionTab;
     m_devicePage = addPage( m_deviceOptionTab, i18n("Devices") );
-    m_devicePage->setHeader( i18n("Setup Devices") );
+    m_devicePage->setHeader( i18n("Optical Devices") );
     m_devicePage->setIcon( KIcon( "drive-optical" ) );
     m_pages.insert( Devices, m_devicePage );
 }


More information about the kde-doc-english mailing list