All pastes #1551937 Raw Edit

Mine

public text v1 · immutable
#1551937 ·published 2009-09-02 20:40 UTC
rendered paste body
#include "discburner.h"
#include "backupthread.h"
#include "burnimagethread.h"
#include "formatthread.h"

#include <QApplication>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusPendingCall>
#include <QCursor>
#include <QDebug>
#include <QMessageBox>
#include <QPainter>
#include <QPaintEngine>
#include <QProcess>
#include <QStyleOptionGraphicsItem>
#include <QSizePolicy>
#include <QFont>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsGridLayout>
#include <QGraphicsLinearLayout>
#include <QTimer>
#include <QTreeWidgetItem>

#include <KDebug>
#include <KUrl>
#include <KIcon>
#include <KLocalizedString>
#include <KSharedConfig>
#include <KToolInvocation>
#include <KDialog>
#include <KFileDialog>
#include <KColorScheme>
#include <KComboBox>
#include <KConfigDialog>
#include <KGlobalSettings>
#include <KPushButton>
#include <KMessageBox>
#include <kworkspace/kworkspace.h>

#include <solid/block.h>
#include <solid/opticaldrive.h>
#include <solid/opticaldisc.h>
#include <solid/device.h>
#include <solid/devicenotifier.h>
#include <solid/deviceinterface.h>

#include <Plasma/Svg>
#include <Plasma/Theme>
#include <Plasma/Animator>
#include <Plasma/Extender>
#include <Plasma/ExtenderItem>
#include <Plasma/PopupApplet>
#include <Plasma/Label>
#include <Plasma/Slider>
#include <Plasma/PushButton>
#include <Plasma/ToolTipManager>
#include <Plasma/TreeView>
#include <Plasma/CheckBox>
#include <Plasma/ComboBox>
#include <Plasma/IconWidget>
#include <Plasma/Meter>

DiscBurner::DiscBurner(QObject *parent, const QVariantList &args)
        : Plasma::PopupApplet(parent, args)
{
    m_isEmbedded = false;
    m_extenderVisible = true,
    m_extenderLayout = 0;
    m_actionsLayout = 0;
    m_driveCombo = 0;
    m_createButton = 0;
    m_burnButton = 0;
    m_backupButton = 0;
    m_copyButton = 0;
    m_ripButton = 0;
    m_formatButton = 0;
    m_meter = 0;
    m_tree = 0;
    m_animId = -1;
    m_alpha = 1;
    m_fadeIn = false;
    m_appletAnimId = -1;
    m_appletAlpha = 1;
    m_appletFadeIn = true;
    m_jobMaximum = 0;
    m_jobProgress = 0;
    m_isHovered = false;
    m_isBusy = false;
    m_firstRun = true;
    m_hasAudioProjectLoaded = false;
    m_hasVideoProjectLoaded = false;
    m_hasDataProjectLoaded = false;
    m_textRect = QRectF();
    m_remainingMSecs = 0;
    m_extenderApplet = 0;
    m_newAudioImageMenu = new QMenu(this->widget());
    m_newVideoImageMenu = new QMenu(this->widget());
    m_newImageMenu = new QMenu(this->widget());
    m_newAudioCDImageAction = new KAction(KIcon("media-optical-audio"), i18n("New Audio CD..."), this);
    m_newMP3CDImageAction = new KAction(KIcon("media-optical-audio"), i18n("New MP3 CD..."), this);
    m_newDataCDImageAction = new KAction(KIcon("media-optical"), i18n("New Data CD..."), this);
    m_newVideoCDImageAction = new KAction(KIcon("media-optical-video"), i18n("New Video CD..."), this);
    m_newDataDVDImageAction = new KAction(KIcon("media-optical-DVD"), i18n("New Data DVD..."), this);
    m_newVideoDVDImageAction = new KAction(KIcon("media-optical-video"), i18n("New Video DVD..."), this);
    m_newMixedModeImageAction = new KAction(KIcon("media-optical-audio"), i18n("New Mixed Mode CD..."), this);
    m_overlayText = "Drop!";
    m_trackDuplicateCount = 0;
    setAcceptsHoverEvents(true);
    setAcceptDrops(true);
    setHasConfigurationInterface(true);
    setPopupIcon(QIcon());
    resize(150, 150);
    setAspectRatioMode(Plasma::Square);
    setBackgroundHints(NoBackground);
}

void DiscBurner::init()
{
    KConfigGroup cg = config();
    m_showOverlayLabel = cg.readEntry("showDropLabel", false);

    showDiscBurner(true);
    readColors();
    setActionState(Idle);
    setInteractionState(Waiting);

    m_icon = new KIcon("k3b");
    m_mainActionsLayout = new QGraphicsGridLayout(this);
    m_ejectButton = new Plasma::IconWidget;
    m_ejectButton->setIcon("media-eject");
    m_ejectButton->setOpacity(0.5);
    m_cancelButton = new Plasma::IconWidget;
    m_cancelButton->setIcon("dialog-cancel");
    m_cancelButton->setVisible(false);
    m_meter = new Plasma::Meter;
    m_meter->setMeterType(Plasma::Meter::BarMeterVertical);
    m_meter->setVisible(false);
    m_busyWidget = new Plasma::BusyWidget;
    m_busyWidget->setRunning(true);
    m_busyWidget->setVisible(false);
    m_mainActionsLayout->addItem(m_ejectButton, 0, 2);
    m_mainActionsLayout->addItem(m_busyWidget, 1, 2);
    m_mainActionsLayout->addItem(m_meter, 0, 0, 3, 1);
    m_mainActionsLayout->addItem(m_cancelButton, 2, 2);
    m_mainActionsLayout->setColumnPreferredWidth(1, 70);
    m_mainActionsLayout->setSpacing(0);
    m_font = QApplication::font();
    m_font.setWeight(QFont::Bold);
    m_boxAlpha = 128;
    m_boxHoverAlpha = 192;
    m_hasAudioProjectLoaded = false;
    m_hasVideoProjectLoaded = false;
    m_hasDataProjectLoaded = false;
    m_newImageMenu->addAction(m_newAudioCDImageAction);
    m_newImageMenu->addAction(m_newVideoCDImageAction);
    m_newImageMenu->addAction(m_newVideoDVDImageAction);
    m_newImageMenu->addAction(m_newDataCDImageAction);
    m_newImageMenu->addAction(m_newDataDVDImageAction);
    m_newImageMenu->addAction(m_newMixedModeImageAction);
    m_newAudioImageMenu->addAction(m_newAudioCDImageAction);
    m_newAudioImageMenu->addAction(m_newMP3CDImageAction);
    m_newAudioImageMenu->addAction(m_newMixedModeImageAction);
    m_newVideoImageMenu->addAction(m_newVideoCDImageAction);
    m_newVideoImageMenu->addAction(m_newVideoDVDImageAction);
    m_newVideoImageMenu->addAction(m_newDataCDImageAction);
    m_newVideoImageMenu->addAction(m_newDataDVDImageAction);
    m_newVideoImageMenu->addAction(m_newMixedModeImageAction);
    m_treeModel = new QStandardItemModel;
    m_treeModel->setSupportedDragActions(Qt::MoveAction);
    m_currentDiscItem = new QStandardItem;
    m_currentProjectItem = new QStandardItem;
    m_currentProjectItems = new QList<QStandardItem*>;
    
    connect(m_newAudioCDImageAction, SIGNAL(triggered()), this, SLOT(on_newAudioCDImage_clicked()));
    connect(m_newVideoCDImageAction, SIGNAL(triggered()), this, SLOT(on_newVideoCDImage_clicked()));
    connect(m_newVideoDVDImageAction, SIGNAL(triggered()), this, SLOT(on_newVideoDVDImage_clicked()));
    connect(m_newDataCDImageAction, SIGNAL(triggered()), this, SLOT(on_newDataCDImage_clicked()));
    connect(m_newDataDVDImageAction, SIGNAL(triggered()), this, SLOT(on_newDataDVDImage_clicked()));
    connect(m_newMixedModeImageAction, SIGNAL(triggered()), this, SLOT(on_newMixedModeImage_clicked()));
    
    connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(readColors()));
    connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), SLOT(readColors()));
    connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(const QString&)), this, SLOT(updateDrives()));
    connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(const QString&)), this, SLOT(updateDrives()));
//todo: solid tray ejection notification
    connect(m_ejectButton, SIGNAL(clicked()), this, SLOT(on_ejectButton_clicked()));
    connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(on_cancelButton_clicked()));

    Plasma::ToolTipManager::self()->registerWidget(this);
    Plasma::ToolTipManager::self()->setContent(this, *m_toolTipData);

    if (!m_isEmbedded && !extender()->hasItem("discburnerlist"))
    {
        Plasma::ExtenderItem *eItem = new Plasma::ExtenderItem(extender());
        eItem->setName("discburnerlist");
        initExtenderItem(eItem);
    }
}

void DiscBurner::paintInterface(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
{
    Q_UNUSED( option );

    p->setRenderHint(QPainter::SmoothPixmapTransform);
    p->setRenderHint(QPainter::Antialiasing);

    int iconsize = iconSize();

    QPointF iconOrigin = QPointF(contentsRect.left() + (contentsRect.width() - iconsize) / 2, contentsRect.top() + (contentsRect.height() - iconsize) / 2);
    QRectF iconRect = QRectF(iconOrigin, QSize(iconsize, iconsize));

    QPixmap ico_pix = m_icon->pixmap(QSize(iconsize, iconsize));

    QPixmap temp(QSize(iconsize, iconsize));
    temp.fill(Qt::transparent);

    if (temp.isNull())
        return;

    QPainter painter;
    painter.begin(&temp);

    painter.setCompositionMode(QPainter::CompositionMode_Source);
    painter.drawPixmap(QPoint(0,0), ico_pix);
    painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);

    painter.end();

    p->drawPixmap(iconOrigin, temp);

    if (m_isHovered)
    {
        paintOverlayText(p, contentsRect, m_overlayText);
    }

    update();
}

void DiscBurner::paintOverlayText(QPainter *p, const QRect &contentsRect, const QString& labelText)
{
    int original_font_size = m_font.pointSize();

    m_font.setPointSize(qMax(KGlobalSettings::smallestReadableFont().pointSize(), m_font.pointSize()));
    QFontMetrics fm(m_font);
    qreal text_width = fm.width(labelText);

    if (labelText.length() > 4) {
        if (original_font_size/1.5 < KGlobalSettings::smallestReadableFont().pointSize()) {
            m_font.setPointSize((KGlobalSettings::smallestReadableFont().pointSize()));
        }
        else {
            m_font.setPointSizeF(original_font_size/1.5);
        }

        fm = QFontMetrics(m_font);
        text_width = (fm.width(labelText) * 1.2);
    }
    else {
        text_width = (text_width * 1.4);
    }

    if (formFactor() == Plasma::Horizontal || formFactor() == Plasma::Vertical) {
        m_font = KGlobalSettings::smallestReadableFont();
        m_font.setWeight(QFont::Bold);
        fm = QFontMetrics(m_font);
        text_width = (fm.width(labelText)+8);
    }

    p->setFont(m_font);

    m_textRect = QRectF(qMax(qreal(0.0), contentsRect.left() + (contentsRect.width() - text_width) / 2), contentsRect.top() + ((contentsRect.height() - (int)fm.height()) / 2 * 0.9), qMin(contentsRect.width(), (int)text_width), fm.height() * 1.2 );

    m_boxColor.setAlphaF(m_alpha);
    p->setPen(m_boxColor);
    m_boxColor.setAlphaF(m_alpha*0.5);
    p->setBrush(m_boxColor);
    float round_prop = m_textRect.width() / m_textRect.height();

    qreal round_radius = 35.0;
    p->drawRoundedRect(m_textRect, round_radius / round_prop, round_radius, Qt::RelativeSize);

    m_textColor.setAlphaF(m_alpha);
    p->setPen(m_textColor);
    p->drawText(m_textRect, Qt::AlignCenter, labelText);
    m_font.setPointSize(original_font_size);
    m_boxColor.setAlpha(m_boxAlpha);
}

void DiscBurner::constraintsEvent(Plasma::Constraints constraints)
{
    int minWidth;
    int minHeight;

    if (constraints & (Plasma::FormFactorConstraint | Plasma::SizeConstraint)) {
        if (formFactor() == Plasma::Vertical) {
            minHeight = qMax(m_textRect.height(), size().width());
            setMinimumWidth(0);
            setMinimumHeight(minHeight);
        }
        else if (formFactor() == Plasma::Horizontal) {
            minWidth = qMax(m_textRect.width(), size().height());
            setMinimumWidth(minWidth);
            setMinimumHeight(0);
        }
        else {
            setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
            setMinimumSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
        }

        m_font.setPointSize(qMax(KGlobalSettings::smallestReadableFont().pointSize(), qRound(contentsRect().height() / 10)));
        update();
    }
}

void DiscBurner::readColors()
{
    m_textColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
    m_boxColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor);
}

void DiscBurner::showAppletLabel(bool show)
{
    if (show != m_showOverlayLabel) {
        showOverlayText(show);
        m_showOverlayLabel = show;
    }
}

void DiscBurner::showOverlayText(bool show)
{
    if (m_fadeIn == show) {
        return;
    }

    m_fadeIn = show;
    const int FadeInDuration = 150;

    if (m_animId != -1) {
        Plasma::Animator::self()->stopCustomAnimation(m_animId);
    }

    m_animId = Plasma::Animator::self()->customAnimation(40 / (1000 / FadeInDuration), FadeInDuration, Plasma::Animator::EaseOutCurve, this, "animationUpdate");
}

void DiscBurner::showDiscBurner(bool show)
{
    if (m_appletFadeIn == show) {
        return;
    }

    m_appletFadeIn = show;
    const int FadeInDuration = 300;

    if (m_appletAnimId != -1) {
        Plasma::Animator::self()->stopCustomAnimation(m_appletAnimId);
    }

    m_appletAnimId = Plasma::Animator::self()->customAnimation(40 / (1000 / FadeInDuration), FadeInDuration, Plasma::Animator::EaseOutCurve, this, "discburnerAnimationUpdate");
}

void DiscBurner::animationUpdate(qreal progress)
{
    if (progress == 1) {
        m_animId = -1;
    }
    if (!m_fadeIn) {
        qreal new_alpha = m_fadeIn ? progress : 1 - progress;
        m_alpha = qMin(new_alpha, m_alpha);
    }
    else {
        m_alpha = m_fadeIn ? progress : 1 - progress;
    }

    m_alpha = qMax(qreal(0.0), m_alpha);
    update();
}

void DiscBurner::appletAnimationUpdate(qreal progress)
{
    if (progress == 1) {
        m_appletAnimId = -1;
    }

    m_appletAlpha = m_appletFadeIn ? progress : 1 - progress;
    update();
}

int DiscBurner::iconSize()
{
    int c = qMin(contentsRect().width(), contentsRect().height());
    int s;
    if (c >= KIconLoader::SizeEnormous) { // 128
        s = KIconLoader::SizeEnormous;
    }
    else if (c >= KIconLoader::SizeHuge) { // 64
        s = KIconLoader::SizeHuge;
    }
    else if (c >= KIconLoader::SizeLarge) { // 48
        s = KIconLoader::SizeLarge;
    }
    else if (c >= KIconLoader::SizeMedium) { // 32
        s = KIconLoader::SizeMedium;
    }
    else if (c >= KIconLoader::SizeSmallMedium) { // 32
        s = KIconLoader::SizeSmallMedium;
    }
    else { // 16
        s = KIconLoader::SizeSmall;
    }
    return s;
}

void DiscBurner::setInteractionState(InteractionState state)
{
    m_interactionState = state;
}

void DiscBurner::setActionState(ActionState state)
{
    m_toolTipData = new Plasma::ToolTipContent();
    m_toolTipData->setAutohide(true);
    m_toolTipData->setMainText("DiscBurner");

    if (!m_toolTipData)
        return;

    switch (state ) {
    case Unset:
        m_toolTipData->setSubText(i18nc("The status of the applet has not been set - i.e. it is unset.", "Unset"));
        m_toolTipData->setImage(KIcon("media-optical-recordable"));
        break;
    case Idle:
        setBusy(false);
        m_toolTipData->setSubText(i18n("Drop files on me to create a disc."));
        m_toolTipData->setImage(KIcon("media-optical-recordable"));
        break;
    case IdleError:
        setBusy(false);
        m_toolTipData->setSubText(i18n("Error. Sorry =["));
        m_toolTipData->setImage(KIcon("dialog-cancel"));
        QTimer::singleShot(10000, this, SLOT(resetActionState()));
        break;
    case IdleSuccess:
        setBusy(false);
        m_toolTipData->setSubText(i18n("Success!"));
        m_toolTipData->setImage(KIcon("dialog-ok"));
        QTimer::singleShot(10000, this, SLOT(resetActionState()));
        break;
    case Burning:
        setBusy(true);
        m_toolTipData->setSubText(i18n("Burning...."));
        m_toolTipData->setImage(KIcon("tools-media-optical-burn"));
        break;
    case Formatting:
        setBusy(true);
        m_toolTipData->setSubText(i18n("Formatting...."));
        m_toolTipData->setImage(KIcon("tools-media-optical-erase"));
        break;
    case Reading:
        setBusy(true);
        m_toolTipData->setSubText(i18n("Reading...."));
        m_toolTipData->setImage(KIcon("tools-media-optical-burn-image"));
        break;
    default:
        break;
    }

    Plasma::ToolTipManager::self()->setContent(this, *m_toolTipData);
    m_actionState = state;
    update();
}

void DiscBurner::createConfigurationInterface(KConfigDialog *parent)
{
    QWidget *widget = new QWidget(parent);
    ui.setupUi(widget);
    parent->addPage(widget, i18n("General"), Applet::icon());
    connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
    connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
    //    ui.showDropLabelCheckBox->setChecked(m_showDropLabel ? Qt::Checked : Qt::Unchecked);
}

void DiscBurner::configAccepted()
{
    KConfigGroup cg = config();

    if (m_showOverlayLabel != ui.showDropLabelCheckBox->isChecked()) {
        m_showOverlayLabel = !m_showOverlayLabel;
        cg.writeEntry("showDropLabel", m_showOverlayLabel);
        if (m_showOverlayLabel && m_showOverlayLabel == ui.showDropLabelCheckBox->isChecked()) {
            showOverlayText(m_showOverlayLabel);
        }
    }

    emit configNeedsSaving();
}

void DiscBurner::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    setInteractionState(Hovered);
    showOverlayText(true);
    m_isHovered = true;
    Applet::hoverEnterEvent(event);
}

void DiscBurner::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    setInteractionState(Waiting);

    if (!m_showOverlayLabel && !m_isEmbedded) {
        showOverlayText(false);
        m_isHovered = false;
    }

    Applet::hoverLeaveEvent(event);
}

DiscBurner::~DiscBurner()
{
    KConfigGroup cg = config();
    //    cg.writeEntry("Config Option Name", variant);
}

void DiscBurner::setupConnections()
{

}

void DiscBurner::setEmbedded(const bool embedded)
{
    m_isEmbedded = embedded;
}

void DiscBurner::setBusy(bool busy)
{
    if(busy) {
        m_overlayText = "Busy...";
    }
    else {
        m_overlayText = "Drop!";
    }

    m_isBusy = busy;
}

void DiscBurner::initExtenderItem(Plasma::ExtenderItem *item)
{
    if (!m_isEmbedded && item->name() == "discburnerlist") {
        QGraphicsWidget *burnlist = new QGraphicsWidget(item);
        burnlist->setMinimumSize(350, 250);

        m_extenderLayout = new QGraphicsLinearLayout(burnlist);
        m_extenderLayout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        m_extenderLayout->setOrientation(Qt::Vertical);

        m_actionsLayout = new QGraphicsGridLayout(m_extenderLayout);
        m_actionsLayout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

        m_driveCombo = new Plasma::ComboBox(burnlist);
        m_driveCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);

        m_extenderLayout->addItem(m_driveCombo);

        m_tree = new Plasma::TreeView(burnlist);
        m_tree->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        m_tree->nativeWidget()->setHeaderHidden(true);
	m_tree->nativeWidget()->setDragDropMode(QAbstractItemView::InternalMove);
	m_tree->nativeWidget()->setSelectionMode(QAbstractItemView::SingleSelection);
	m_tree->nativeWidget()->setAnimated(true);
	m_tree->nativeWidget()->viewport()->setAcceptDrops(true);
	m_tree->setAcceptHoverEvents(true);
	m_tree->setAcceptDrops(true);
	m_tree->setModel(m_treeModel);

        updateDrives();

        m_extenderLayout->addItem(m_tree);

        m_createButton = new Plasma::IconWidget(burnlist);
        m_createButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
        m_createButton->setIcon("media-optical");
        m_createButton->setOrientation(Qt::Horizontal);
        m_createButton->setDrawBackground(true);
        m_createButton->setTextBackgroundColor(QColor());
        m_createButton->setText(i18n("Create"));
        m_createButton->setMaximumHeight(36);

        m_actionsLayout->addItem(m_createButton, 0, 0);

        m_burnButton = new Plasma::IconWidget(burnlist);
        m_burnButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
        m_burnButton->setIcon("tools-media-optical-burn");
        m_burnButton->setOrientation(Qt::Horizontal);
        m_burnButton->setDrawBackground(true);
        m_burnButton->setTextBackgroundColor(QColor());
        m_burnButton->setText(i18n("Burn"));
        m_burnButton->setMaximumHeight(36);

        m_actionsLayout->addItem(m_burnButton, 0, 1);

        m_backupButton = new Plasma::IconWidget(burnlist);
        m_backupButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
        m_backupButton->setIcon("tools-media-optical-burn-image");
        m_backupButton->setOrientation(Qt::Horizontal);
        m_backupButton->setDrawBackground(true);
        m_backupButton->setTextBackgroundColor(QColor());
        m_backupButton->setText(i18n("Backup"));
        m_backupButton->setMaximumHeight(36);

        m_actionsLayout->addItem(m_backupButton, 0, 2);

        m_copyButton = new Plasma::IconWidget(burnlist);
        m_copyButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
        m_copyButton->setIcon("tools-media-optical-copy");
        m_copyButton->setOrientation(Qt::Horizontal);
        m_copyButton->setDrawBackground(true);
        m_copyButton->setTextBackgroundColor(QColor());
        m_copyButton->setText(i18n("Copy"));
        m_copyButton->setMaximumHeight(36);

        m_actionsLayout->addItem(m_copyButton, 1, 0);

        m_ripButton = new Plasma::IconWidget(burnlist);
        m_ripButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
        m_ripButton->setIcon("media-optical-audio");
        m_ripButton->setOrientation(Qt::Horizontal);
        m_ripButton->setDrawBackground(true);
        m_ripButton->setTextBackgroundColor(QColor());
        m_ripButton->setText(i18n("Rip"));
        m_ripButton->setMaximumHeight(36);

        m_actionsLayout->addItem(m_ripButton, 1, 1);

        m_formatButton = new Plasma::IconWidget(burnlist);
        m_formatButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
        m_formatButton->setIcon("tools-media-optical-format");
        m_formatButton->setOrientation(Qt::Horizontal);
        m_formatButton->setDrawBackground(true);
        m_formatButton->setTextBackgroundColor(QColor());
        m_formatButton->setText(i18n("Format"));
        m_formatButton->setMaximumHeight(36);

        m_actionsLayout->addItem(m_formatButton, 1, 2);

        m_extenderLayout->addItem(m_actionsLayout);

        burnlist->setLayout(m_extenderLayout);

        connect(m_createButton, SIGNAL(clicked()), this, SLOT(on_createButton_clicked()));
        connect(m_burnButton, SIGNAL(clicked()), this, SLOT(on_burnButton_clicked()));
        connect(m_backupButton, SIGNAL(clicked()), this, SLOT(on_backupButton_clicked()));
        connect(m_copyButton, SIGNAL(clicked()), this, SLOT(on_copyButton_clicked()));
        connect(m_ripButton, SIGNAL(clicked()), this, SLOT(on_ripButton_clicked()));
        connect(m_formatButton, SIGNAL(clicked()), this, SLOT(on_formatButton_clicked()));

        DiscBurner *m_extenderApplet = static_cast<DiscBurner*>(Plasma::Applet::load("discburner"));

        if (m_extenderApplet) {
            m_extenderApplet->setParent(this);
            m_extenderApplet->setAcceptsHoverEvents(false);
            m_extenderApplet->setParentItem(burnlist);
            m_extenderApplet->setEmbedded(true);
            m_extenderApplet->setMinimumSize(80, 80);
            m_extenderApplet->resize(80, 80);
            m_extenderApplet->setBackgroundHints(NoBackground);
            m_extenderApplet->setFlag(QGraphicsItem::ItemIsMovable, false);
            m_extenderApplet->init();
            m_extenderApplet->updateConstraints(Plasma::StartupCompletedConstraint);
        }

        burnlist->setLayout(m_extenderLayout);
        item->setIcon("tools-media-optical-burn");
        item->setWidget(burnlist);
        item->setTitle(i18n("DiscBurner"));
    }
}

void DiscBurner::resetActionState()
{
    setActionState(Idle);
    update();
}

void DiscBurner::popupEvent(bool show)
{
    m_extenderVisible = show;
    updateStatus();
}

void DiscBurner::updateStatus()
{
    if (!m_extenderVisible) {
        return;
    }
}

void DiscBurner::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
    InteractionState istate = Rejected;
    if (event->mimeData()->hasFormat("text/plain")) {
        event->acceptProposedAction();
    }

    if (event->mimeData()->hasText()) {
        istate = DraggedOver;
    }

    setInteractionState(istate);

    showOverlayText(true);
    m_isHovered = true;
    Applet::dragEnterEvent(event);
}

void DiscBurner::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
    setInteractionState(Waiting);

    if (!m_showOverlayLabel && !m_isEmbedded) {
        showOverlayText(false);
        m_isHovered = false;
    }
    event->accept();
}

void DiscBurner::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
    event->accept();
}

void DiscBurner::dropEvent(QGraphicsSceneDragDropEvent *event)
{
    if (event->mimeData()->objectName() != QString("discburner-applet")) {
        QList<QUrl> dropped_paths = event->mimeData()->urls();
	kDebug() << dropped_paths;

	foreach (QUrl path, dropped_paths)
	{
	    QString s_path = path.toString().right(path.toString().length() - 7);
	    kDebug() << s_path;

	    if (s_path.right(3).toLower() == "mp3" || s_path.right(3).toLower() == "wav" || s_path.right(3).toLower() == "ogg") {
		if(m_hasAudioProjectLoaded) {
		    addSong(s_path);
		}
		else {
		    m_newAudioImageMenu->exec(event->screenPos());
		}
	    }
	    else if (s_path.right(3) == "mpg" || s_path.right(3) == "avi") {
		if(m_hasVideoProjectLoaded) {
		    //addVideo(s_path);
		}
		else {
		    m_newVideoImageMenu->exec(event->screenPos());
		}
	    }
	    else if (s_path.right(3).toLower() == "iso") {
		burnIso(s_path);
	    }
	    else if (QDir(s_path).exists())
	    {
		kDebug() << "folder dropped";
	    }
	    else {
		if(m_hasDataProjectLoaded) {
    //               addFile(s_path);
		}
		else if(m_hasAudioProjectLoaded) {
		  
		}
		else if (m_hasVideoProjectLoaded) {
		  
		}
		else {
		    m_newImageMenu->exec(event->screenPos());
		}
	    }
	}
        event->acceptProposedAction();
    }
}

void DiscBurner::updateDrives()
{
    m_devicesHash.clear();

    foreach (const Solid::Device &device, Solid::Device::listFromType(Solid::DeviceInterface::OpticalDrive, QString())) {
        const Solid::Block *block_device = device.as<Solid::Block>();

        m_currentDriveUdi = device.udi();

        foreach (const Solid::Device &disc_dev, Solid::Device::listFromType(Solid::DeviceInterface::OpticalDisc, QString())) {
            m_currentDiscUdi = disc_dev.udi();
            m_currentDiscContentType = disc_dev.as<Solid::OpticalDisc>()->availableContent();
            m_currentDiscUsage = QString::number((disc_dev.as<Solid::OpticalDisc>()->size() / 1024) / 1024) + " MB";
            m_currentDiscCapacity = QString::number((disc_dev.as<Solid::OpticalDisc>()->capacity() / 1024) / 1024) + " MB";
	    m_currentDiscLabel = disc_dev.as<Solid::StorageVolume>()->label();

            if (m_currentDiscContentType== Solid::OpticalDisc::Audio) {
                m_icon = new KIcon("media-optical-audio");
                m_currentDiscContentTypeString = "Audio Disc";
            }
            else if (m_currentDiscContentType== Solid::OpticalDisc::Data) {
                m_icon = new KIcon("media-optical");
                m_currentDiscContentTypeString = "Data Disc";
            }
            else if (disc_dev.as<Solid::OpticalDisc>()->isBlank()) {
                m_icon = new KIcon("media-optical-recordable");
                m_currentDiscContentTypeString = "Blank Disc";
            }
            else {
                m_icon = new KIcon("media-optical-video");
                m_currentDiscContentTypeString = "Video Disc";
            }
        }

        m_devicesHash.insert(block_device->device(), device.product());
    }

    m_driveCombo->nativeWidget()->clear();

    foreach(QString value, m_devicesHash) {
        m_driveCombo->nativeWidget()->addItem(KIcon("drive-optical"), value);
    }

    if (m_devicesHash.isEmpty())
        m_driveCombo->nativeWidget()->addItem(KIcon("drive-optical"), "No Devices Found");

    updateCurrentDisc();

    update();
}

void DiscBurner::on_createButton_clicked()
{
    m_newImageMenu->exec(QCursor::pos());
}

void DiscBurner::on_burnButton_clicked()
{
    if(m_hasAudioProjectLoaded)
    {
      
    }
    else if (m_hasDataProjectLoaded)
    {
      
    }
    else if (m_hasVideoProjectLoaded)
    {
      
    }
    else if (m_currentDiscContentTypeString == "Blank Disc")
    {
	QString filename = KFileDialog::getOpenFileName(KUrl(QDir::homePath()), "*.iso|ISO9660 Image Files (*.iso)\n*.bin|Binary Image Files (*.bin)\n*.toc|Table of Contents Files (*.toc)\n*.nrg|Nero Image Files (*.nrg)\n*.cue|CloneImage Files (*.cue)", this->widget(), "Select Image File");
	burnIso(filename);
    }
}

void DiscBurner::on_backupButton_clicked()
{
    if (m_currentDiscContentTypeString == "Blank Disc") {
        QMessageBox::critical(this->widget(), "Error", "Can't backup a blank disc.");
        return;
    }

    KUrl url ( QDir::homePath() );
    QProcess p(0);
    QString dev;
    QString fileName;
    if (m_currentDiscContentType== Solid::OpticalDisc::Audio) {
        if(QMessageBox::question(this->widget(), "Really create .bin?", "Audio CDs are not ISO filesystems. They should be decoded into .ogg/.mp3. Continue creating .bin/.toc files? [FOR ADVANCED USERS]", QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel) == QMessageBox::Yes) {
            fileName = KFileDialog::getSaveFileName(url, "BIN Files (*.bin)", this->widget(), "Save BIN file");
        }
        else {
            return;
        }
    }
    else {
        fileName = KFileDialog::getSaveFileName(url, "ISO Files (*.iso)", this->widget(), "Save ISO file");
    }

    QHashIterator<QString, QString> i(m_devicesHash);
    while (i.hasNext()) {
        i.next();
        if (i.value() == m_driveCombo->text()) {
            dev = i.key();
        }
    }
    if (!dev.isEmpty()) {
        setActionState(Reading);
        m_cancelButton->setVisible(true);
        m_busyWidget->setVisible(true);
        m_meter->setVisible(true);
        BackupThread *backup = new BackupThread(this->widget(), dev, fileName, m_currentDiscUdi, m_currentDiscContentType);
        connect(backup, SIGNAL(discCapacity(int)), this, SLOT(setJobMaximum(int)));
        connect(backup, SIGNAL(progressMonitor(int)), this, SLOT(setJobProgress(int)));
        connect(backup, SIGNAL(finished()), this, SLOT(jobCompleted()));
        connect(this, SIGNAL(cancelProcesses()), backup, SLOT(cancelProcess()));
        backup->run();
        update();
    }
}

void DiscBurner::on_copyButton_clicked()
{

}

void DiscBurner::on_ripButton_clicked()
{

}

void DiscBurner::on_formatButton_clicked()
{
    if (m_currentDiscContentTypeString == "Blank Disc") {
        if(QMessageBox::question(this->widget(), "Disc Already Blank", "This disc appears to already be blank. Format it again anyway?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
	    return;
	}
    }

    QHashIterator<QString, QString> i(m_devicesHash);
    QString dev;
    while (i.hasNext()) {
        i.next();
        if (i.value() == m_driveCombo->text()) {
            dev = i.key();
        }
    }
    if (!dev.isEmpty()) {
        this->hidePopup();
        m_cancelButton->setVisible(false);
        m_busyWidget->setVisible(true);
        setActionState(Formatting);
        FormatThread *formatter = new FormatThread(this->widget(), dev, m_currentDiscUdi);
        connect(formatter, SIGNAL(finished()), this, SLOT(jobCompleted()));
        connect(this, SIGNAL(cancelProcesses()), formatter, SLOT(cancelProcess()));
        formatter->run();
        update();
    }
}

void DiscBurner::setJobMaximum(int max)
{
    m_jobMaximum = max;
}

void DiscBurner::setJobProgress(int progress)
{
    m_toolTipData = new Plasma::ToolTipContent();
    m_toolTipData->setAutohide(true);
    m_toolTipData->setMainText("DiscBurner");

    m_jobProgress = progress;

    if(m_jobMaximum > 0 && m_jobProgress > 0 && m_jobProgress < 100) {
        m_currentProgress = (m_jobProgress * 100) / m_jobMaximum;
        if (m_currentProgress == 0 || m_currentProgress == 100) {
            qDebug() << "currentProgress=" << m_currentProgress;
            qDebug() << "jobProgress=" << m_jobProgress;
            qDebug() << "jobMaximum=" << m_jobMaximum;
        }
    }

    if ((m_currentProgress > 100))
        return;

    if (m_actionState == Reading) {
        m_toolTipData->setSubText("Creating backup...<br>" + QString::number(m_currentProgress) + "% Complete");
    }
    else if (m_actionState == Burning) {
        if (m_currentProgress == 0) {
            m_toolTipData->setSubText("Burning...<br>Caching Data");
        }
        else if (m_currentProgress == 100) {
            m_toolTipData->setSubText("Burning...<br>Finalizing Media");
        }
        else {
            m_toolTipData->setSubText("Burning...<br>" + QString::number(m_currentProgress) + "% Complete");
        }
    }
    else if (m_actionState == Formatting) {
        m_toolTipData->setSubText("Formatting...");
    }

    Plasma::ToolTipManager::self()->setContent(this, *m_toolTipData);

    m_meter->setMaximum(100);
    m_meter->setValue(m_currentProgress);

    update();
}

void DiscBurner::jobCompleted()
{
    m_jobProgress = m_jobMaximum;
    m_currentProgress = 100;
    setActionState(IdleSuccess);
    setBusy(false);
    m_cancelButton->setVisible(false);
    m_busyWidget->setVisible(false);
    m_meter->setVisible(false);
    on_ejectButton_clicked();
    update();
}

void DiscBurner::burnIso(QString url)
{
    QString dev;
    QHashIterator<QString, QString> i(m_devicesHash);
    while (i.hasNext()) {
        i.next();
        if (i.value() == m_driveCombo->text()) {
            dev = i.key();
        }
    }

    if (!dev.isEmpty()) {
        m_cancelButton->setVisible(true);
        m_busyWidget->setVisible(true);
        m_meter->setVisible(true);
        setActionState(Burning);
        BurnImageThread *burner = new BurnImageThread(this, dev, url, m_currentDiscUdi);
        connect(burner, SIGNAL(discCapacity(int)), this, SLOT(setJobMaximum(int)));
        connect(burner, SIGNAL(progressMonitor(int)), this, SLOT(setJobProgress(int)));
        connect(burner, SIGNAL(finished()), this, SLOT(jobCompleted()));
        connect(this, SIGNAL(cancelProcesses()), burner, SLOT(cancelProcess()));
        burner->run();
    }
}

void DiscBurner::updateCurrentDisc()
{
    if (m_currentDiscUdi.isEmpty() || m_currentDiscUdi.isNull())
        return;

    m_tree->nativeWidget()->setIconSize(QSize(24,24));

    m_currentDiscItem->setIcon(*m_icon);
    m_currentDiscItem->setText(m_currentDiscContentTypeString + "     " + m_currentDiscUsage + "/" + m_currentDiscCapacity + "\n" + m_currentDiscLabel);
    m_currentDiscItem->setSizeHint(QSize(500,50));
    m_currentDiscItem->setDropEnabled(false);
    m_currentDiscItem->setDragEnabled(false);
    m_currentDiscItem->setEditable(false);

    if(!m_treeModel->itemFromIndex(m_currentDiscItem->index()))
    {
	m_treeModel->appendRow(m_currentDiscItem);
	m_treeModel->setSupportedDragActions(Qt::MoveAction);
    }

}

void DiscBurner::on_ejectButton_clicked()
{
//    Solid::Device current_drive = Solid::Device::Device(m_currentDriveUdi);
//    current_drive.as<Solid::OpticalDrive>()->eject();
    QProcess::startDetached("eject -T");
    updateDrives();
}

void DiscBurner::on_cancelButton_clicked()
{
    emit cancelProcesses();
}

void DiscBurner::on_newAudioCDImage_clicked()
{
    if(m_hasAudioProjectLoaded)
      return;

    m_currentProjectItem->setIcon(KIcon("folder-sound"));
    m_currentProjectItem->setText("Audio Disc");
    m_currentProjectItem->setToolTip("Double-Click to change disc label");
    m_currentProjectItem->setEditable(true);
    m_currentProjectItem->setEnabled(true);
    m_currentProjectItem->setSelectable(false);
    m_currentProjectItem->setDropEnabled(true);
    m_currentProjectItem->setDragEnabled(false);
    m_currentProjectItem->setSizeHint(QSize(500,32));
    m_currentDiscItem->appendRow(m_currentProjectItem);
    m_tree->nativeWidget()->expand(m_currentDiscItem->index());
    m_tree->nativeWidget()->setIndentation(10);
    m_tree->installEventFilter(this);
    m_hasAudioProjectLoaded = true;
}

void DiscBurner::on_newVideoCDImage_clicked()
{
  
}

void DiscBurner::on_newVideoDVDImage_clicked()
{
  
}

void DiscBurner::on_newDataCDImage_clicked()
{
  
}

void DiscBurner::on_newDataDVDImage_clicked()
{
  
}

void DiscBurner::on_newMixedModeImage_clicked()
{
  
}

void DiscBurner::addSong(QString url)
{
    QStandardItem *song = new QStandardItem;
    QStandardItem *songFileName = new QStandardItem;
    QStandardItem *songSize = new QStandardItem;
    QStandardItem *songLength = new QStandardItem;
    QStandardItem *songArtist = new QStandardItem;
    QStandardItem *songTitle = new QStandardItem;
    
    song->setText(QFileInfo(url).baseName());
    song->setSizeHint(QSize(500,28));
    song->setIcon(KIcon("audio-x-generic"));
    m_currentProjectItem->appendRow(song);
    m_tree->nativeWidget()->expand(m_currentProjectItem->index());
    songFileName->setText("Filename: " + url);
    songFileName->setToolTip(url);
    m_tagFileRef = TagLib::FileRef(url.toAscii().data());
    m_tagFileTags = m_tagFileRef.tag();
    m_tagFileProperties = m_tagFileRef.audioProperties();
    songLength->setText("Length: " + QString::number(m_tagFileProperties->length()));
    songLength->setEditable(false);
    songArtist->setText("Artist: " + TStringToQString(m_tagFileTags->artist()));
    songTitle->setText("Title: " + TStringToQString(m_tagFileTags->title()));
    songSize->setText("Size: " + QString::number(QFileInfo(url).size() / 1024 / 1024) + " MB");
    songSize->setEditable(false);
    song->appendRow(songArtist);
    song->appendRow(songTitle);
    song->appendRow(songLength);
    song->appendRow(songFileName);
    song->appendRow(songSize);
    song->setDragEnabled(true);
    song->setDropEnabled(false);
    song->setEnabled(true);
    song->setSelectable(true);

    m_currentProjectItems->append(song);
}

bool DiscBurner::eventFilter(QObject *obj, QEvent *event)
{
    if (qobject_cast< Plasma::TreeView* >(obj))
    {
	if (event->type() == QEvent::GraphicsSceneDrop)
	{
	    int i = 0;
	    while(i < m_currentProjectItem->rowCount())
	    {
		kDebug() << m_currentProjectItem->child(i)->text();
		m_currentProjectItem->child(i)->setEnabled(true);
		m_currentProjectItem->child(i)->setSelectable(true);
		m_currentProjectItem->child(i)->setIcon(KIcon("audio-x-generic"));
		kDebug() << "woot!";
		i++;
		kDebug() << i;
	    }
	}
	else
	{
	    return QObject::eventFilter(obj, event);
	}
    }
    else
    {
      return QObject::eventFilter(obj, event);
    }

    return QObject::eventFilter(obj, event);
}

#include "discburner.moc"