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>&lt;p&gt;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.&lt;/p&gt;
-&lt;p&gt;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>&lt;qt&gt;&lt;b&gt;Hint:&lt;/b&gt; to force K3b to use 
another than the default name for the executable specify it in the search 
path.&lt;/qt&gt;</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>&amp;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 );
 }

Reply via email to