/* ** Copyright (C) 2000 Peter Putzer ** */ /* ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program in a file called COPYING; if not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ** MA 02110-1301, USA. */ /* ** Bug reports and questions can be sent to kde-devel@kde.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; version 2. * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kdltooltip.h" #include "ksv_core.h" #include "ksv_conf.h" #include "ksvdraglist.h" #include "ksvdrag.h" #include "ActionList.h" KSVItem::KSVItem (TDEListView* view) : TQListViewItem (view), mData (new KSVData()), mConfig (KSVConfig::self()), mNewNormalColor (mConfig->newNormalColor()), mNewSelectedColor (mConfig->newSelectedColor()), mChangedNormalColor (mConfig->changedNormalColor()), mChangedSelectedColor (mConfig->changedSelectedColor()) { } KSVItem::KSVItem (const KSVItem& item) : TQListViewItem (item.listView()), mData (new KSVData(*item.mData)), mConfig (KSVConfig::self()), mNewNormalColor (mConfig->newNormalColor()), mNewSelectedColor (mConfig->newSelectedColor()), mChangedNormalColor (mConfig->changedNormalColor()), mChangedSelectedColor (mConfig->changedSelectedColor()) { setText (SortNumber, mData->numberString()); setText (ServiceName, label()); setIcon (*item.pixmap(Icon)); } KSVItem::KSVItem (KSVDragList* view, const KSVData& data) : TQListViewItem (view), mData (new KSVData (data)), mConfig (KSVConfig::self()), mNewNormalColor (mConfig->newNormalColor()), mNewSelectedColor (mConfig->newSelectedColor()), mChangedNormalColor (mConfig->changedNormalColor()), mChangedSelectedColor (mConfig->changedSelectedColor()) { setText (SortNumber, mData->numberString()); setText (ServiceName, label()); setIcon (view->defaultIcon()); } void KSVItem::copy (const KSVData& item) { *mData = item; setText (SortNumber, mData->numberString()); setText (ServiceName, mData->label()); } TQString KSVItem::key (int, bool) const { return mData->numberString() + mData->label(); } KSVItem::KSVItem (TDEListView* view, TQString file, TQString path, TQString label, TQ_INT8 nr ) : TQListViewItem (view), mData (new KSVData (file, path, label, nr)), mConfig (KSVConfig::self()), mNewNormalColor (mConfig->newNormalColor()), mNewSelectedColor (mConfig->newSelectedColor()), mChangedNormalColor (mConfig->changedNormalColor()), mChangedSelectedColor (mConfig->changedSelectedColor()) { setText (ServiceName, mData->label()); setText (SortNumber, mData->numberString()); } KSVItem::~KSVItem() { delete mData; } void KSVItem::paintCell (TQPainter* p, const TQColorGroup& cg, int column, int width, int align) { switch (column) { case SortNumber: p->setFont (mConfig->numberFont()); break; case ServiceName: p->setFont (mConfig->serviceFont()); break; } TQColorGroup colors = cg; if (mData->newEntry()) { colors.setColor (TQColorGroup::Text, mNewNormalColor); colors.setColor (TQColorGroup::HighlightedText, mNewSelectedColor); } else if (mData->changed()) { colors.setColor (TQColorGroup::Text, mChangedNormalColor); colors.setColor (TQColorGroup::HighlightedText, mChangedSelectedColor); } TQListViewItem::paintCell (p, colors, column, width, align); } TQString KSVItem::toString() const { return filenameAndPath(); } TQString KSVItem::tooltip () const { TQString result; if (mConfig->showDescription()) { if (!ksv::getServiceDescription(filename(), result)) result = toString(); else { // split into nice chunks result = ksv::breakWords(result.simplifyWhiteSpace(), 50); } } else { result = toString(); } return result; } void KSVItem::setNew ( bool val ) { mData->setNewEntry (val); } TQPixmap KSVItem::paintDragIcon (const TQFont& font, const TQColorGroup&) const { TQFontMetrics metric (font); TQRect textRect = metric.boundingRect (label()); const TQPixmap& icon = *pixmap (Icon); const int margin = listView()->itemMargin(); const int width = icon.width() + margin * 2 + textRect.width(); const int height = kMax (icon.height(), textRect.height()); TQPixmap result (width, height); result.fill (white); TQPainter p (&result); p.drawPixmap (0, 0, icon); p.setFont (font); p.drawText (icon.width() + margin, 0, width, height, AlignLeft | AlignVCenter, label()); p.end(); TQBitmap mask (width, height); p.begin (&mask); p.setFont (font); p.fillRect (0, 0, width, height, color0); p.setPen (color1); p.drawPixmap (0, 0, icon.createHeuristicMask()); p.drawText (icon.width() + margin, 0, width, height, AlignLeft | AlignVCenter, label()); TQBrush brush (color0); brush.setStyle(Qt::Dense5Pattern); p.fillRect (0, 0, width, height, brush); p.end(); result.setMask(mask); result.setOptimization(TQPixmap::BestOptim); return result; } void KSVItem::setIcon (const TQPixmap& icon) { setPixmap (Icon, icon); } void KSVItem::setLabel (const TQString& label) { mData->setLabel (label); setText (ServiceName, label); } void KSVItem::setRunlevel (const TQString& runlevel) { mData->setRunlevel (runlevel); } void KSVItem::setFilename (const TQString& file) { mData->setFilename (file); } void KSVItem::setNumber (TQ_INT8 nr) { mData->setNumber (nr); setText(SortNumber, mData->numberString()); } void KSVItem::setPath (const TQString& path) { mData->setPath (path); } void KSVItem::setNewNormalColor (const TQColor& col) { mNewNormalColor = col; } void KSVItem::setNewSelectedColor (const TQColor& col) { mNewSelectedColor = col; } void KSVItem::setChangedNormalColor (const TQColor& col) { mChangedNormalColor = col; } void KSVItem::setChangedSelectedColor (const TQColor& col) { mChangedSelectedColor = col; } void KSVItem::setChanged (bool val) { mData->setChanged (val); } void KSVItem::setOriginalRunlevel (const TQString& rl) { mData->setOriginalRunlevel (rl); } //----------------------- // KSVDragList //----------------------- KSVDragList::KSVDragList ( TQWidget* parent, const char* name ) : TDEListView (parent, name), mItemToDrag (0L), mDragMenu (new TDEPopupMenu (this)), mDragCopyMenu (new TDEPopupMenu (this)), mDragMoveMenu (new TDEPopupMenu (this)), mDisplayToolTips (true), mCommonToolTips (true) { // add tooltips toolTip=new KDLToolTip (this); setDragEnabled (true); setDragAutoScroll(true); setAcceptDrops(true); setDropVisualizer (true); TQHeader* h = header(); h->setClickEnabled (false); addColumn (i18n("No.")); // SortNumber // setColumnWidthMode (KSVItem::SortNumber, Manual); addColumn (""); // Icon // setColumnWidthMode (KSVItem::Icon, Manual); addColumn (i18n("Name")); // ServiceName // setColumnWidthMode (KSVItem::ServiceName, Manual); h->setResizeEnabled (false, KSVItem::Icon); setShowSortIndicator (false); setAllColumnsShowFocus (true); // multiselection is to complicated due to the sorting numbers setSelectionModeExt (Single); // init DND menu mDragMenu->insertTitle (i18n("Drag Menu")); mDragMenu->insertItem ("&Copy", Copy); mDragMenu->insertItem ("&Move", Move); mDragCopyMenu->insertTitle (i18n("Drag Menu")); mDragCopyMenu->insertItem ("&Copy", Copy); mDragMoveMenu->insertTitle (i18n("Drag Menu")); mDragMoveMenu->insertItem ("&Move", Move); mRMList.setAutoDelete(true); // catch drops connect (this, TQT_SIGNAL (dropped (TQDropEvent*, TQListViewItem*)), this, TQT_SLOT (drop (TQDropEvent*, TQListViewItem*))); } KSVDragList::~KSVDragList() { delete mDragMenu; delete mDragCopyMenu; delete mDragMoveMenu; delete toolTip; } void KSVDragList::initItem (TQString file, TQString path, TQString name, TQ_INT8 nr) { KSVItem* tmp = new KSVItem(this, file, path, name, nr); tmp->setRunlevel(TQT_TQOBJECT(this)->name()); tmp->setOriginalRunlevel(TQT_TQOBJECT(this)->name()); tmp->setIcon (mIcon); setUpdatesEnabled(false); // marked as new in insert, we don't want that tmp->setNew(false); tmp->setChanged (false); setUpdatesEnabled(true); repaint(false); } void KSVDragList::setDefaultIcon (const TQPixmap& icon) { mIcon = icon; for (TQListViewItemIterator it (firstChild()); it.current(); ++it) { static_cast (it.current())->setIcon (mIcon); } } void KSVDragList::clear () { TDEListView::clear(); clearRMList(); } void KSVDragList::setNewNormalColor ( const TQColor& col ) { mNewNormalColor = col; KSVItem* item; for (TQListViewItemIterator it (firstChild()); (item = static_cast(it.current())); ++it) { item->setNewNormalColor (mNewNormalColor); } } void KSVDragList::setNewSelectedColor (const TQColor& col) { mNewSelectedColor = col; KSVItem* item; for (TQListViewItemIterator it (firstChild()); (item = static_cast(it.current())); ++it) { item->setNewSelectedColor (mNewSelectedColor); } } TQ_INT8 KSVDragList::generateNumber (const TQString& label, const KSVData* itemBelow, const KSVData* itemAbove) const { TQ_INT8 high = itemBelow ? itemBelow->number() : -1; TQ_INT8 low = itemAbove ? itemAbove->number() : -1; TQ_INT8 result = generateNumber (high, low); if (high == result && result != -1 && label >= itemBelow->label()) result = -1; if (low == result && result != -1 && label <= itemAbove->label()) result = -1; return result; } TQ_INT8 KSVDragList::generateNumber (TQ_INT8 high, TQ_INT8 low) const { Q_ASSERT (high >= low || high == -1); TQ_INT8 result = -1; if (low < 0) { if (high < 0) result = 50; else result = high / 2; } else if (high < 0) result = (100 - low) / 2 + low; else result = (high - low) / 2 + low; return result; } void KSVDragList::setChangedNormalColor (const TQColor& col) { mChangedNormalColor = col; KSVItem* item; for (TQListViewItemIterator it (firstChild()); (item = static_cast (it.current())); ++it) { item->setChangedNormalColor (mChangedNormalColor); } } void KSVDragList::setChangedSelectedColor (const TQColor& col) { mChangedSelectedColor = col; KSVItem* item; for (TQListViewItemIterator it (firstChild()); (item = static_cast (it.current())); ++it) { item->setChangedSelectedColor (mChangedSelectedColor); } } KSVItem* KSVDragList::match (const KSVData& data) { KSVItem* res = 0L; for (TQListViewItemIterator it (this); (res = static_cast (it.current())); ++it) { if (*res->data() == data) break; else res = 0L; } return res; } void KSVDragList::setOrigin (bool val) { mOrigin = val; if (mOrigin) { emit newOrigin (this); emit newOrigin(); } else clearSelection(); } void KSVDragList::startDrag () { mItemToDrag = static_cast (currentItem()); KSVDrag* d = dynamic_cast (dragObject()); if (d) { d->setPixmap (mItemToDrag->paintDragIcon (font(), colorGroup())); d->drag(); } } //KSVDrag* KSVDragList::dragObject () TQDragObject* KSVDragList::dragObject () { if (mItemToDrag) { return new KSVDrag (*mItemToDrag, this); } else return 0L; } bool KSVDragList::acceptDrag (TQDropEvent* e) const { e->acceptAction (); return acceptDrops() && e->provides ("application/x-ksysv"); } void KSVDragList::focusInEvent (TQFocusEvent* e) { TDEListView::focusInEvent(e); if (!currentItem()) setCurrentItem (firstChild()); setOrigin(true); } void KSVDragList::clearRMList() { mRMList.clear(); } bool KSVDragList::removeFromRMList (const KSVData& item) { KSVData* res = 0L; for (TQPtrListIterator it (mRMList); it.current(); ++it) { res = it.current(); if (*res == item) break; else res = 0L; } if (res) return mRMList.remove (res); else return false; } bool KSVDragList::insert (const KSVData& data, const KSVData* above, const KSVData* below) { TQ_INT8 nr = generateNumber (data.label(), below, above); if (nr > -1) { KSVData real (data); real.setNumber (nr); KSVItem* item = new KSVItem (this, real); item->setNew (true); return true; } else emit cannotGenerateNumber (); return false; } bool KSVDragList::insert (const KSVData& data, const KSVItem* where, KSVAction*& action) { const KSVData* above = 0L; const KSVData* below = 0L; if (where) { above = where->data(); KSVItem* tmp = static_cast (where->nextSibling()); below = tmp ? tmp->data() : 0L; } else { KSVItem* tmp = static_cast (firstChild()); below = tmp ? tmp->data() : 0L; } bool success = false; KSVItem* exists = match (data); action = 0L; if (exists) { if (exists->data() == above || exists->data() == below) return false; TQ_INT8 nr = generateNumber (exists->label(), below, above); if (nr == -1) { emit cannotGenerateNumber(); } else { KSVData oldState = *exists->data(); exists->setNumber (nr); sort(); action = new ChangeAction (this, &oldState, exists->data()); success = true; } } else { success = insert (data, above, below); if (success) action = new AddAction (this, match (data)->data()); } return success; } void KSVDragList::drop (TQDropEvent* e, TQListViewItem* after) { KSVData data; KSVDragList* source = static_cast (e->source()); TQPopupMenu* menu = 0L; // hack to empty the cursor stack after DND TQApplication::restoreOverrideCursor(); TQApplication::restoreOverrideCursor(); if ((!source) || (!strcmp(source->name(), "Scripts"))) menu = mDragCopyMenu; else if (source == this) menu = mDragMoveMenu; else menu = mDragMenu; if (KSVDrag::decodeNative (e, data)) { int res = -1; if (e->action() == TQDropEvent::Copy && source != this) res = Copy; else res = menu->exec (TQCursor::pos(), 1); if (res == -1) // operation cancelled return; const bool move = res == Move; KSVItem* tmp = static_cast (after); KSVAction* action = 0L; if (insert (data, tmp, action)) { if (move && source != this) { KSVAction* actions[2]; actions [0] = new RemoveAction (source, &data); actions [1] = action; action = new CompoundAction (actions, 2); delete source->match (data); } emit undoAction (action); } } } bool KSVDragList::addToRMList (const KSVData& item) { KSVData* res = 0L; for (TQPtrListIterator it (mRMList); it.current(); ++it) { res = it.current(); if (*res == item) break; else res = 0L; } if (!res) { mRMList.append (new KSVData(item)); return true; } else return false; } void KSVDragList::setEnabled (bool enable) { if (enable) clearWState (WState_ForceDisabled); else setWState (WState_ForceDisabled); if (enable) { if (testWState (WState_Disabled)) { clearWState (WState_Disabled); // setBackgroundFromMode(); // this is private in TQWidget... // well it doesn't really matter in this case enabledChange( TRUE ); } } else { if (!testWState(WState_Disabled)) { if (focusWidget() == this) focusNextPrevChild (TRUE); setWState (WState_Disabled); // setBackgroundFromMode(); // this is private in TQWidget... // well it doesn't really matter in this case enabledChange (FALSE); } } viewport()->setEnabled (enable); } // KServiceDragList KServiceDragList::KServiceDragList (TQWidget* parent, const char* name) : KSVDragList (parent, name) { } KServiceDragList::~KServiceDragList () { } void KServiceDragList::startDrag () { mItemToDrag = static_cast (currentItem()); KSVDrag* d = dynamic_cast (dragObject()); if (d) { d->setPixmap (mItemToDrag->paintDragIcon (font(), colorGroup())); d->dragCopy(); } } #include "ksvdraglist.moc"