/*************************************************************************** plugin_katetabbarextension.cpp ------------------- begin : 2004-04-20 copyright : (C) 2004 by Dominik Haumann email : dhdev@gmx.de ***************************************************************************/ /*************************************************************************** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ***************************************************************************/ // BEGIN INCLUDES #include "plugin_katetabbarextension.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // END class PluginView : public KXMLGUIClient { friend class KatePluginTabBarExtension; public: Kate::MainWindow *win; KateTabBarExtension* tabbar; }; extern "C" { KDE_EXPORT void* init_libkatetabbarextensionplugin() { TDEGlobal::locale()->insertCatalogue("katetabbarextension"); return new KatePluginFactory; } } TQObject* KatePluginFactory::createObject(TQObject *parent, const char *name, const char*, const TQStringList&) { return new KatePluginTabBarExtension(parent, name); } TDEInstance* KatePluginFactory::s_instance = 0L; // BEGIN KatePluginTabBarExtension KatePluginTabBarExtension::KatePluginTabBarExtension(TQObject *parent, const char *name) : Kate::Plugin((Kate::Application*)parent, name), pConfig(new TDEConfig("katetabbarextensionpluginrc")) { pConfig->setGroup("global"); } KatePluginTabBarExtension::~KatePluginTabBarExtension() { while (m_views.count() > 0) { removeView(m_views.at(0)->win); } delete pConfig; } void KatePluginTabBarExtension::addView(Kate::MainWindow *win) { PluginView *view = new PluginView (); bool bHoriz = pConfig->readBoolEntry("horizontal orientation", true); bool bSort = pConfig->readBoolEntry("sort", true); bool bCloseOnMiddleClick = pConfig->readBoolEntry("closeOnMiddleClick", false); view->tabbar = new KateTabBarExtension(application()->documentManager(), win, bHoriz, bSort, bCloseOnMiddleClick, 0, "tabs_hbox"); new KWidgetAction(view->tabbar, "tab_bar_widget", TDEShortcut::null(), 0, 0, view->actionCollection(), "tabbar_widget"); view->setInstance (new TDEInstance("kate")); view->setXMLFile("plugins/katetabbarextension/ui.rc"); win->guiFactory()->addClient (view); view->win = win; m_views.append (view); TDEToolBar* toolbar = dynamic_cast (win->guiFactory()->container("tabbarExtensionToolBar", view)); if (toolbar) { connect(toolbar, TQ_SIGNAL(orientationChanged(TQt::Orientation)), view->tabbar, TQ_SLOT(slotMoved(TQt::Orientation))); } } void KatePluginTabBarExtension::removeView(Kate::MainWindow *win) { for (uint z=0; z < m_views.count(); z++) { if (m_views.at(z)->win == win) { PluginView *view = m_views.at(z); // the last tabbar, save options if (m_views.count() == 1) { pConfig->writeEntry("horizontal orientation", view->tabbar->orientation()==TQt::Horizontal?true:false); pConfig->writeEntry("sort", view->tabbar->sortByName()); pConfig->writeEntry("closeOnMiddleClick", view->tabbar->closeOnMiddleClick()); pConfig->sync(); } m_views.remove (view); win->guiFactory()->removeClient (view); delete view->tabbar; delete view; } } } Kate::PluginConfigPage* KatePluginTabBarExtension::configPage( uint, TQWidget *w, const char* /*name*/) { KateTabBarExtensionConfigPage* p = new KateTabBarExtensionConfigPage(this, w); initConfigPage( p ); connect( p, TQ_SIGNAL(configPageApplyRequest(KateTabBarExtensionConfigPage*)), TQ_SLOT(applyConfig(KateTabBarExtensionConfigPage*)) ); return (Kate::PluginConfigPage*)p; } void KatePluginTabBarExtension::initConfigPage(KateTabBarExtensionConfigPage *p) { p->pSortAlpha->setChecked(m_views.at(0)->tabbar->sortByName()); p->pCloseOnMiddleClick->setChecked(m_views.at(0)->tabbar->closeOnMiddleClick()); } void KatePluginTabBarExtension::applyConfig(KateTabBarExtensionConfigPage *p) { m_views.at(0)->tabbar->setSortByName(p->pSortAlpha->isChecked()); m_views.at(0)->tabbar->setCloseOnMiddleClick(p->pCloseOnMiddleClick->isChecked()); // sync m_config in destructor } // END KatePluginTabBarExtension // BEGIN KateTabBarButton KateTabBarButton::KateTabBarButton(Kate::ViewManager* pViewManager, Kate::Document *pDoc, TQWidget * parent, const char * name) : TQPushButton(parent, name), modified(false), myDocID(pDoc->documentNumber()), doc(pDoc), viewManager(pViewManager) { setFlat(true); setToggleButton(true); setFocusPolicy(TQWidget::NoFocus); setText(pDoc->docName()); connect(this, TQ_SIGNAL(toggled(bool)), TQ_SLOT(setOn(bool))); } void KateTabBarButton::setDirty(bool d) { if (d) { setIconSet(SmallIconSet("cancel")); } else { if (modified) setIconSet(SmallIconSet("modified")); else setIconSet(TQIconSet()); } } void KateTabBarButton::setText( const TQString& newText) { TQToolTip::remove(this); if (newText.length() > 20) { // squeeze to length 17+3=20 TQPushButton::setText(newText.left(9) + "..." + newText.right(8)); TQToolTip::add(this, newText); } else { TQPushButton::setText(newText); } } void KateTabBarButton::mouseReleaseEvent(TQMouseEvent *e) { // Only handle middle click events when no keyboard modifier is pressed if (e->button() == TQt::MidButton && !(e->state() & TQt::KeyButtonMask)) { emit middleButtonPressed(this); } else { // Invoke parent handler for unwanted events TQPushButton::mouseReleaseEvent(e); } } TQString KateTabBarButton::fullName() const { if (doc) { return doc->docName(); } else { return TQString(""); } } void KateTabBarButton::triggerModified() { modified = !modified; if (modified) { TQColor c(255, 0, 0); setPaletteForegroundColor( c ); setIconSet(SmallIconSet("modified")); } else { TQColor c(TDEGlobalSettings::textColor()); setPaletteForegroundColor( c ); setIconSet(TQIconSet()); } } void KateTabBarButton::setOn(bool on) { disconnect( TQ_SIGNAL(toggled(bool))); // kdDebug() << "setOn: " << (int)on << endl; if ((!on) && viewManager->activeView()->document()->documentNumber() == documentNumber()) { // kdDebug() << "setOn aborted " << endl; TQPushButton::setOn(true); } else { TQPushButton::setOn(on); if (on) emit myToggled(this); } connect(this, TQ_SIGNAL(toggled(bool)), TQ_SLOT(setOn(bool))); } // END KateTabBarButton // BEGIN KateTabBarExtension KateTabBarExtension::KateTabBarExtension(Kate::DocumentManager *pDocManager, Kate::MainWindow *win, bool bHorizOrientation, bool bSort, bool bCloseOnMiddleClick, TQWidget* parent, const char* name, WFlags f) : TQWidget(parent, name, f), pCurrentTab(0), m_win(win), m_docManager(pDocManager), m_sort(false) { if (bHorizOrientation) { top = new TQBoxLayout(this, TQBoxLayout::LeftToRight); m_orientation = TQt::Horizontal; } else { top = new TQBoxLayout(this, TQBoxLayout::TopToBottom); m_orientation = TQt::Vertical; } // add all already existing documents to the tabbar for (uint i = 0; i < pDocManager->documents(); i++) { slotDocumentCreated (pDocManager->document(i)); } connect(m_win->viewManager(), TQ_SIGNAL(viewChanged()), TQ_SLOT(slotViewChanged())); connect(pDocManager, TQ_SIGNAL(documentCreated(Kate::Document *)), TQ_SLOT(slotDocumentCreated(Kate::Document *))); connect(pDocManager, TQ_SIGNAL(documentDeleted(uint)), TQ_SLOT(slotDocumentDeleted(uint))); setSortByName(bSort); setCloseOnMiddleClick(bCloseOnMiddleClick); } void KateTabBarExtension::slotMoved(TQt::Orientation o) { // the tabbar moved (top, right, bottom, left or fluently) switch (o) { case TQt::Vertical: top->setDirection(TQBoxLayout::TopToBottom); break; case TQt::Horizontal: top->setDirection(TQBoxLayout::LeftToRight); break; } m_orientation = o; } void KateTabBarExtension::setSortByName(bool sbn) { if (m_sort != sbn) { m_sort = sbn; if (m_sort) updateSort(); } } void KateTabBarExtension::updateSort() { // kdDebug() << "updateSort called" << endl; if (sortByName()) { // remove all tabs from the tabbar KateTabBarButton* tab; for (tab = m_tabs.first(); tab; tab = m_tabs.next() ) { top->remove(tab); } // now sort m_tabs.sort(); // and finally add tabs again. FIXME: Is there a better way? :( for (tab = m_tabs.first(); tab; tab = m_tabs.next() ) { top->addWidget(tab); } } } void KateTabBarExtension::slotDocumentCreated (Kate::Document *doc) { // kdDebug() << "slotDocumentCreated" << endl; if (!doc) return; KateTabBarButton* tab = new KateTabBarButton(m_win->viewManager(), doc, this); connect(tab, TQ_SIGNAL(myToggled(KateTabBarButton*)), TQ_SLOT(slotActivateView(KateTabBarButton*))); connect(tab, TQ_SIGNAL(middleButtonPressed(KateTabBarButton*)), TQ_SLOT(slotRequestDocClose(KateTabBarButton*))); connect(doc, TQ_SIGNAL(nameChanged(Kate::Document *)), TQ_SLOT(slotNameChanged(Kate::Document *))); connect(doc, TQ_SIGNAL(modStateChanged(Kate::Document *)), TQ_SLOT(slotModChanged(Kate::Document *))); connect(doc, TQ_SIGNAL(modifiedOnDisc(Kate::Document *, bool, unsigned char)), TQ_SLOT(slotModifiedOnDisc(Kate::Document *, bool, unsigned char))); if(doc->isModified()) tab->triggerModified(); tab->show(); top->addWidget(tab); m_tabs.append(tab); updateSort(); } void KateTabBarExtension::slotDocumentDeleted (uint documentNumber) { // kdDebug() << "slotDocumentDeleted " << endl; KateTabBarButton* tab; for (tab = m_tabs.first(); tab; tab = m_tabs.next() ) { if (tab->documentNumber() == documentNumber) { tab->disconnect(); top->remove(tab); m_tabs.removeRef(tab); delete tab; tab = 0; break; } } } void KateTabBarExtension::slotActivateView(KateTabBarButton* newTab) { // kdDebug() << "slotActiavateView" << endl; pCurrentTab = newTab; if (pCurrentTab) { KateTabBarButton* tab; for (tab = m_tabs.first(); tab; tab = m_tabs.next() ) { if (tab->isOn() && tab != pCurrentTab) tab->setOn(false); } uint id = pCurrentTab->documentNumber(); m_win->viewManager()->activateView( id ); } } void KateTabBarExtension::slotModChanged (Kate::Document *doc) { // kdDebug() << "slotModChanged" << endl; if (!doc) return; KateTabBarButton* tab; for (tab = m_tabs.first(); tab; tab = m_tabs.next() ) { if (tab->documentNumber() == doc->documentNumber()) { // found tab->triggerModified(); break; } } } void KateTabBarExtension::slotModifiedOnDisc ( Kate::Document *doc, bool b, unsigned char /*reason*/) { // kdDebug() << "slotModifiedOnDisc: " << (int)b << endl; // find corresponding tab KateTabBarButton* tab; for (tab = m_tabs.first(); tab; tab = m_tabs.next() ) { if (tab->documentNumber() == doc->documentNumber()) { tab->setDirty(b); } } } void KateTabBarExtension::slotNameChanged (Kate::Document *doc) { if (!doc) return; // kdDebug() << "slotNameChanged " << doc->docName() << endl; KateTabBarButton* tab; for (tab = m_tabs.first(); tab; tab = m_tabs.next() ) { if (tab->documentNumber() == doc->documentNumber()) { tab->setText(doc->docName()); break; } } updateSort(); } void KateTabBarExtension::slotViewChanged () { // kdDebug() << "slotVieChanged()" << endl; Kate::View *view = m_win->viewManager()->activeView(); if (!view) return; KateTabBarButton* tab; for (tab = m_tabs.first(); tab; tab = m_tabs.next() ) { if (tab->documentNumber() == ((Kate::Document *)view->getDoc())->documentNumber()) { pCurrentTab = tab; for (tab = m_tabs.first(); tab; tab = m_tabs.next() ) { if (tab->isOn()) tab->setOn(false); } if (!pCurrentTab->isOn()) pCurrentTab->setOn(true); break; } } } void KateTabBarExtension::slotRequestDocClose(KateTabBarButton *tab) { if (closeOnMiddleClick() && tab) { m_docManager->closeDocument(tab->document()); } } // END KateTabBarExtension // BEGIN KateTabBarExtensionConfigPage KateTabBarExtensionConfigPage::KateTabBarExtensionConfigPage( TQObject* /*parent*/ /*= 0L*/, TQWidget *parentWidget /*= 0L*/) : Kate::PluginConfigPage( parentWidget ) { TQVBoxLayout* top = new TQVBoxLayout(this, 0, KDialogBase::spacingHint()); TQGroupBox* gb = new TQGroupBox(1, TQt::Horizontal, i18n("Behavior options"), this, "tab_bar_extension_config_page_layout" ); gb->setInsideSpacing(KDialogBase::spacingHint()); pSortAlpha = new TQCheckBox(i18n("Sort files alphabetically"), gb); pCloseOnMiddleClick = new TQCheckBox(i18n("Close document on mouse middle click"), gb); top->add(gb); top->addStretch(1); // throw signal changed connect(pSortAlpha, TQ_SIGNAL(toggled(bool)), this, TQ_SIGNAL(changed())); connect(pCloseOnMiddleClick, TQ_SIGNAL(toggled(bool)), this, TQ_SIGNAL(changed())); } // END KateTabBarExtensionConfigPage // BEGIN MyPtrList implementaion int MyPtrList::compareItems ( TQPtrCollection::Item item1_, TQPtrCollection::Item item2_ ) { KateTabBarButton* item1 = reinterpret_cast(item1_); KateTabBarButton* item2 = reinterpret_cast(item2_); if (item1->fullName().lower() < item2->fullName().lower()) { // kdDebug() << item1->fullName().lower() << " < " // << item2->fullName().lower() << endl; return -1; } else { if (item1->fullName().lower() > item2->fullName().lower()) { // kdDebug() << item1->fullName().lower() << " > " // << item2->fullName().lower() << endl; return 1; } else { // kdDebug() << item1->fullName().lower() << " == " // << item2->fullName().lower() << endl; return 0; } } } // END MyPtrList implementaion #include "plugin_katetabbarextension.moc"