/*************************************************************************** * Copyright (C) 2003-2005 by David Saxton * * david@bluehaze.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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "circuitdocument.h" #include "contexthelp.h" #include "docmanager.h" #include "filemetainfo.h" #include "flowcodedocument.h" #include "itemeditor.h" #include "itemgroup.h" #include "iteminterface.h" #include "itemlibrary.h" #include "ktechlab.h" #include "core/ktlconfig.h" #include "languagemanager.h" #include "mechanicsdocument.h" #include "microlibrary.h" #include "newfiledlg.h" #include "oscilloscope.h" #include "projectmanager.h" #include "recentfilesaction.h" #include "settingsdlg.h" #include "subcircuits.h" #include "symbolviewer.h" #include "textdocument.h" #include "textview.h" #include "viewcontainer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include KTechlab::KTechlab() : KateMDI::MainWindow( 0, "KTechlab" ) { TQTime ct; ct.start(); m_bIsShown = false; m_pContainerDropSource = 0l; m_pContainerDropReceived = 0l; m_pContextMenuContainer = 0l; m_pFocusedContainer = 0l; m_pToolBarOverlayLabel = 0l; m_pUpdateCaptionsTimer = new TQTimer( this ); connect( m_pUpdateCaptionsTimer, TQT_SIGNAL(timeout()), TQT_TQOBJECT(this), TQT_SLOT(slotUpdateCaptions()) ); setMinimumSize( 400, 400 ); DocManager::self(this); ItemInterface::self(this); setupTabWidget(); setupToolDocks(); setupActions(); setupView(); readProperties( TDEGlobal::config() ); // kdDebug() << "Constructor time: " << ct.elapsed() << endl; } KTechlab::~KTechlab() { fileMetaInfo()->saveAllMetaInfo(); delete fileMetaInfo(); delete itemLibrary(); // This better be the last time the item library is used! delete subcircuits(); } void KTechlab::show() { KateMDI::MainWindow::show(); m_bIsShown = true; } void KTechlab::load( const KURL & url ) { if ( url.url().endsWith( ".ktechlab", false ) ) { // This is a ktechlab project; it has to be handled separetly from a // normal file. ProjectManager::self()->slotOpenProject( url ); return; } TQString target; // the below code is what you should normally do. in this // example case, we want the url to our own. you probably // want to use this code instead for your app // download the contents if ( !TDEIO::NetAccess::download( url, target, this ) ) { // If the file could not be downloaded, for example does not // exist on disk, NetAccess will tell us what error to use KMessageBox::error(this, TDEIO::NetAccess::lastErrorString()); return; } addRecentFile(url); // set our caption setCaption( url.prettyURL() ); // load in the file (target is always local) DocManager::self()->openURL( target ); // and remove the temp file TDEIO::NetAccess::removeTempFile( target ); } TQStringList KTechlab::recentFiles() { return m_recentFiles->items(); } void KTechlab::setupToolDocks() { #if defined(TDE_MAKE_VERSION) # if TDE_VERSION >= TDE_MAKE_VERSION(3,3,0) setToolViewStyle( KMultiTabBar::KDEV3ICON ); # endif #endif TQPixmap pm; TDEIconLoader * loader = TDEGlobal::iconLoader(); KateMDI::ToolView * tv = 0l; tv = createToolView( ProjectManager::toolViewIdentifier(), KMultiTabBar::Left, loader->loadIcon( "attach", TDEIcon::Small ), i18n("Project") ); ProjectManager::self( this, tv ); pm.load( locate( "appdata", "icons/circuit.png" ) ); tv = createToolView( ComponentSelector::toolViewIdentifier(), KMultiTabBar::Left, pm, i18n("Components") ); ComponentSelector::self(tv); // Create an instance of the subcircuits interface, now that we have created the component selector subcircuits(); Subcircuits::loadSubcircuits(); pm.load( locate( "appdata", "icons/flowcode.png" ) ); tv = createToolView( FlowPartSelector::toolViewIdentifier(), KMultiTabBar::Left, pm, i18n("Flow Parts") ); FlowPartSelector::self(tv); #ifdef MECHANICS pm.load( locate( "appdata", "icons/mechanics.png" ) ); tv = createToolView( MechanicsSelector::toolViewIdentifier(), KMultiTabBar::Left, pm, i18n("Mechanics") ); MechanicsSelector::self(tv); #endif pm.load( locate( "appdata", "icons/item.png" ) ); tv = createToolView( ItemEditor::toolViewIdentifier(), KMultiTabBar::Right, pm, i18n("Item Editor") ); ItemEditor::self(tv); tv = createToolView( ContextHelp::toolViewIdentifier(), KMultiTabBar::Right, loader->loadIcon( "contents", TDEIcon::Small ), i18n("Context Help") ); ContextHelp::self(tv); tv = createToolView( LanguageManager::toolViewIdentifier(), KMultiTabBar::Bottom, loader->loadIcon( "text-x-log", TDEIcon::Small ), i18n("Messages") ); LanguageManager::self( tv, this ); #ifndef NO_GPSIM tv = createToolView( SymbolViewer::toolViewIdentifier(), KMultiTabBar::Right, loader->loadIcon( "blockdevice", TDEIcon::Small ), i18n("Symbol Viewer") ); SymbolViewer::self(tv); #endif addOscilloscopeAsToolView(this); } void KTechlab::addWindow( ViewContainer * vc ) { if ( vc && !m_viewContainerList.contains(vc) ) { m_viewContainerList << vc; connect( vc, TQT_SIGNAL(destroyed(TQObject* )), TQT_TQOBJECT(this), TQT_SLOT(slotViewContainerDestroyed(TQObject* )) ); } m_viewContainerList.remove((ViewContainer*)0); slotUpdateTabWidget(); slotDocModifiedChanged(); } void KTechlab::setupView() { setAcceptDrops(true); setStandardToolBarMenuEnabled(true); setXMLFile("ktechlabui.rc"); createShellGUI(true); action("newfile_popup")->plug( toolBar("mainToolBar"), 0 ); action("file_new")->unplug( toolBar("mainToolBar") ); statusBar()->show(); } void KTechlab::overlayToolBarScreenshot() { if ( !m_pToolBarOverlayLabel ) { m_pToolBarOverlayLabel = new TQLabel( 0, 0, WStyle_StaysOnTop | WStyle_Customize | WStyle_NoBorder | WNoAutoErase | WType_Popup ); m_pToolBarOverlayLabel->hide(); m_pToolBarOverlayLabel->setBackgroundMode( NoBackground ); } if ( !m_bIsShown ) { // The window isn't visible yet, so there's nothing to overlay (and if we tried, // it would appear as a strange floating toolbar). return; } if ( m_pToolBarOverlayLabel->isShown() ) { // This is to avoid successive calls to removeGUIClient when we have // already popped it up for the first call, and don't want to take // another screenshot (as that would be without the toolbar). return; } TQPtrListIterator toolBarIterator(); // TQWidget * toolsWidget = toolBar( "toolsToolBar" ); // TQWidget * debugWidget = toolBar( "debugTB" ); TDEToolBar * toolsWidget = static_cast(TQT_TQWIDGET(child( "toolsToolBar", "TDEToolBar" ))); TDEToolBar * debugWidget = static_cast(TQT_TQWIDGET(child( "debugTB", "TDEToolBar" ))); if ( !toolsWidget && !debugWidget ) return; TQWidget * parent = TQT_TQWIDGET(toolsWidget ? toolsWidget->parent() : debugWidget->parent()); TQRect grabRect; // 128 is a sanity check (widget can do strange things when being destroyed) if ( toolsWidget && toolsWidget->height() <= 128 ) grabRect |= toolsWidget->geometry(); if ( debugWidget && debugWidget->height() <= 128 ) grabRect |= debugWidget->geometry(); if ( !grabRect.isValid() ) return; TQPixmap shot = TQPixmap::grabWidget( parent, grabRect.x(), grabRect.y(), grabRect.width(), grabRect.height() ); m_pToolBarOverlayLabel->move( parent->mapToGlobal( grabRect.topLeft() ) ); m_pToolBarOverlayLabel->setFixedSize( grabRect.size() ); m_pToolBarOverlayLabel->setPixmap( shot ); m_pToolBarOverlayLabel->show(); TQTimer::singleShot( 100, TQT_TQOBJECT(this), TQT_SLOT( hideToolBarOverlay() ) ); } void KTechlab::hideToolBarOverlay() { if ( !m_pToolBarOverlayLabel ) return; // TQWidget * hiddenWidget = toolBar( "toolsToolBar" ); // if ( !hiddenWidget ) // return; // hiddenWidget->setBackgroundMode( NoBackground ); // hiddenWidget->setWFlags( WNoAutoErase ); // hiddenWidget->setUpdatesEnabled( false ); m_pToolBarOverlayLabel->hide(); } void KTechlab::addNoRemoveGUIClient( KXMLGUIClient * client ) { if ( client && !m_noRemoveGUIClients.contains( client ) ) m_noRemoveGUIClients << client; } void KTechlab::removeGUIClients() { TQValueList clientsToRemove; TQPtrList clients = factory()->clients(); for ( KXMLGUIClient * client = clients.first(); client; client = clients.next() ) { if ( client && client != this && !m_noRemoveGUIClients.contains( client ) ) clientsToRemove << client; } if ( clients.isEmpty() ) return; overlayToolBarScreenshot(); TQValueList::iterator end = clientsToRemove.end(); for ( TQValueList::iterator it = clientsToRemove.begin(); it != end; ++it ) factory()->removeClient(*it); } void KTechlab::setupTabWidget() { m_pViewContainerTabWidget = new KTabWidget(centralWidget()); connect( tabWidget(), TQT_SIGNAL(currentChanged(TQWidget* )), TQT_TQOBJECT(this), TQT_SLOT(slotViewContainerActivated(TQWidget* )) ); connect( tabWidget(), TQT_SIGNAL(testCanDecode(const TQDragMoveEvent*, bool& )), TQT_TQOBJECT(this), TQT_SLOT(slotTabDragEvent(const TQDragMoveEvent*, bool& )) ); connect( tabWidget(), TQT_SIGNAL(initiateDrag(TQWidget* )), TQT_TQOBJECT(this), TQT_SLOT(slotTabDragInitiate(TQWidget* )) ); connect( tabWidget(), TQT_SIGNAL(receivedDropEvent(TQDropEvent* )), TQT_TQOBJECT(this), TQT_SLOT(slotTabReceivedDropEvent(TQDropEvent* )) ); connect( tabWidget(), TQT_SIGNAL(receivedDropEvent(TQWidget*, TQDropEvent* )), TQT_TQOBJECT(this), TQT_SLOT(slotTabReceivedDropEvent(TQWidget*, TQDropEvent* )) ); TDEConfig *config = kapp->config(); config->setGroup("UI"); bool CloseOnHover = config->readBoolEntry( "CloseOnHover", false ); tabWidget()->setHoverCloseButton( CloseOnHover ); bool CloseOnHoverDelay = config->readBoolEntry( "CloseOnHoverDelay", false ); tabWidget()->setHoverCloseButtonDelayed( CloseOnHoverDelay ); // bool openNewTabAfterCurrent = config->readBoolEntry( "OpenNewTabAfterCurrent", false ); // bool showTabIcons = config->readBoolEntry( "ShowTabIcons", true ); if (config->readBoolEntry( "ShowCloseTabsButton", true )) { TQToolButton *but = new TQToolButton(tabWidget()); but->setIconSet(SmallIcon("tab_remove")); but->adjustSize(); but->hide(); connect( but, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(slotViewContainerClose()) ); tabWidget()->setCornerWidget(but, TopRight); } // tabWidget()->setTabReorderingEnabled(true); // connect(tabWidget(), TQT_SIGNAL(movedTab(int, int)), TQT_TQOBJECT(this), TQT_SLOT(tabMoved(int, int))); connect(tabWidget(), TQT_SIGNAL(contextMenu(TQWidget*,const TQPoint &)), TQT_TQOBJECT(this), TQT_SLOT(slotTabContext(TQWidget*,const TQPoint &))); //END Tab bar stuff } void KTechlab::slotUpdateTabWidget() { m_viewContainerList.remove( (ViewContainer*)0 ); bool noWindows = m_viewContainerList.isEmpty(); if ( TQWidget * button = tabWidget()->cornerWidget(TopRight) ) button->setHidden( noWindows ); if ( noWindows ) setCaption( 0 ); } void KTechlab::setupActions() { TDEActionCollection *ac = actionCollection(); KStdAction::openNew( TQT_TQOBJECT(this), TQT_SLOT(slotFileNew()), ac ); KStdAction::open( TQT_TQOBJECT(this), TQT_SLOT(slotFileOpen()), ac ); KStdAction::save( TQT_TQOBJECT(this), TQT_SLOT(slotFileSave()), ac ); KStdAction::saveAs( TQT_TQOBJECT(this), TQT_SLOT(slotFileSaveAs()), ac ); KStdAction::close( TQT_TQOBJECT(this), TQT_SLOT(slotViewClose()), ac ); KStdAction::print( TQT_TQOBJECT(this), TQT_SLOT(slotFilePrint()), ac ); KStdAction::quit( TQT_TQOBJECT(this), TQT_SLOT(slotFileQuit()), ac ); KStdAction::undo( TQT_TQOBJECT(this), TQT_SLOT(slotEditUndo()), ac ); KStdAction::redo( TQT_TQOBJECT(this), TQT_SLOT(slotEditRedo()), ac ); KStdAction::cut( TQT_TQOBJECT(this), TQT_SLOT(slotEditCut()), ac ); KStdAction::copy( TQT_TQOBJECT(this), TQT_SLOT(slotEditCopy()), ac ); KStdAction::paste( TQT_TQOBJECT(this), TQT_SLOT(slotEditPaste()), ac ); KStdAction::keyBindings( TQT_TQOBJECT(this), TQT_SLOT(slotOptionsConfigureKeys()), ac ); KStdAction::configureToolbars( TQT_TQOBJECT(this), TQT_SLOT(slotOptionsConfigureToolbars()), ac ); KStdAction::preferences( TQT_TQOBJECT(this), TQT_SLOT(slotOptionsPreferences()), ac ); //BEGIN New file popup TDEToolBarPopupAction *p = new TDEToolBarPopupAction( i18n("&New"), "document-new", TDEStdAccel::shortcut(TDEStdAccel::New), TQT_TQOBJECT(this), TQT_SLOT(slotFileNew()), ac, "newfile_popup" ); p->popupMenu()->insertTitle( i18n("New File") ); (new TDEAction( i18n("Assembly"), "text-x-src", 0, TQT_TQOBJECT(this), TQT_SLOT(slotFileNewAssembly()), ac, "newfile_asm" ))->plug( p->popupMenu() ); (new TDEAction( i18n("C source"), "text-x-csrc", 0, TQT_TQOBJECT(this), TQT_SLOT(slotFileNewC()), ac, "newfile_c" ))->plug( p->popupMenu() ); (new TDEAction( i18n("Circuit"), "ktechlab_circuit", 0, TQT_TQOBJECT(this), TQT_SLOT(slotFileNewCircuit()), ac, "newfile_circuit" ))->plug( p->popupMenu() ); (new TDEAction( i18n("FlowCode"), "ktechlab_flowcode", 0, TQT_TQOBJECT(this), TQT_SLOT(slotFileNewFlowCode()), ac, "newfile_flowcode" ))->plug( p->popupMenu() ); #ifdef MECHANICS (new TDEAction( i18n("Mechanics"), "ktechlab_mechanics", 0, TQT_TQOBJECT(this), TQT_SLOT(slotFileNewMechanics()), ac, "newfile_mechanics" ))->plug( p->popupMenu() ); #endif (new TDEAction( "Microbe", "ktechlab_microbe", 0, TQT_TQOBJECT(this), TQT_SLOT(slotFileNewMicrobe()), ac, "newfile_microbe" ))->plug( p->popupMenu() ); //END New File popup // m_recentFiles = KStdAction::openRecent( TQT_TQOBJECT(this), TQT_SLOT(load(const KURL&)), ac ); m_recentFiles = new RecentFilesAction( "Recent Files", i18n("Open Recent"), TQT_TQOBJECT(this), TQT_SLOT(load(const KURL &)), ac, "file_open_recent" ); m_statusbarAction = KStdAction::showStatusbar( TQT_TQOBJECT(this), TQT_SLOT(slotOptionsShowStatusbar()), ac ); //BEGIN Project Actions ProjectManager *pm = ProjectManager::self(this); new TDEAction( i18n("New Project.."), "window-new", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotNewProject()), ac, "project_new" ); new TDEAction( i18n("Open Project..."), "project_open", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotOpenProject()), ac, "project_open" ); // m_recentProjects = new TDERecentFilesAction( i18n("Open &Recent Project..."), 0, ProjectManager::self(), TQT_SLOT(slotOpenProject(const KURL&)), ac, "project_open_recent" ); m_recentProjects = new RecentFilesAction( "Recent Projects", i18n("Open &Recent Project..."), TQT_TQOBJECT(ProjectManager::self()), TQT_SLOT(slotOpenProject(const KURL&)), ac, "project_open_recent" ); new TDEAction( i18n("Export to Makefile..."), "fileexport", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotExportToMakefile()), ac, "project_export_makefile" ); new TDEAction( i18n("Create Subproject..."), 0, 0, TQT_TQOBJECT(pm), TQT_SLOT(slotCreateSubproject()), ac, "project_create_subproject" ); new TDEAction( i18n("Add Existing File..."), "document-open", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotAddFile()), ac, "project_add_existing_file" ); new TDEAction( i18n("Add Current File..."), "fileimport", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotAddCurrentFile()), ac, "project_add_current_file" ); // new TDEAction( i18n("Project Options"), "configure", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotProjectOptions()), ac, "project_options" ); new TDEAction( i18n("Close Project"), "window-close", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotCloseProject()), ac, "project_close" ); new TDEAction( i18n("Remove from Project"), "edit-delete", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotRemoveSelected()), ac, "project_remove_selected" ); new TDEAction( i18n("Insert Existing File..."), "document-open", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotSubprojectAddExistingFile()), ac, "subproject_add_existing_file" ); new TDEAction( i18n("Insert Current File..."), "fileimport", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotSubprojectAddCurrentFile()),ac, "subproject_add_current_file" ); new TDEAction( i18n("Linker Options..."), "configure", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotSubprojectLinkerOptions()), ac, "project_item_linker_options" ); new TDEAction( i18n("Build..."), "launch", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotItemBuild()), ac, "project_item_build" ); new TDEAction( i18n("Upload..."), "convert_to_pic", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotItemUpload()), ac, "project_item_upload" ); new TDEAction( i18n("Processing Options..."), "configure", 0, TQT_TQOBJECT(pm), TQT_SLOT(slotItemProcessingOptions()), ac, "project_item_processing_options" ); //END Project Actions new TDEAction( i18n("Split View Left/Right"), "view_right", TQt::CTRL|TQt::SHIFT|TQt::Key_L, TQT_TQOBJECT(this), TQT_SLOT(slotViewSplitLeftRight()), ac, "view_split_leftright" ); new TDEAction( i18n("Split View Top/Bottom"), "view_bottom", TQt::CTRL|TQt::SHIFT|TQt::Key_T, TQT_TQOBJECT(this), TQT_SLOT(slotViewSplitTopBottom()), ac, "view_split_topbottom" ); TDEToggleAction * ta = new TDEToggleAction( i18n("Run Simulation"), "media-playback-start", TQt::Key_F10, 0, 0, ac, "simulation_run" ); ta->setChecked(true); connect( ta, TQT_SIGNAL(toggled(bool )), Simulator::self(), TQT_SLOT(slotSetSimulating(bool )) ); #if defined(TDE_MAKE_VERSION) # if TDE_VERSION >= TDE_MAKE_VERSION(3,3,0) ta->setCheckedState( KGuiItem( i18n("Pause Simulation"), "media-playback-pause", 0 ) ); # endif #endif // We can call slotCloseProject now that the actions have been created ProjectManager::self(this)->updateActions(); DocManager::self(this)->disableContextActions(); } void KTechlab::slotViewContainerActivated( TQWidget * viewContainer ) { if (m_pFocusedContainer) m_pFocusedContainer->setUnfocused(); m_pFocusedContainer = dynamic_cast(viewContainer); if ( !m_pFocusedContainer ) return; m_pFocusedContainer->setFocused(); } void KTechlab::slotViewContainerDestroyed( TQObject * object ) { m_viewContainerList.remove( static_cast(TQT_TQWIDGET(object)) ); m_viewContainerList.remove( (ViewContainer*)0 ); slotUpdateTabWidget(); } void KTechlab::slotTabDragEvent( const TQDragMoveEvent *e, bool &accept ) { // Hmm...this function doesn't actually seem to get called. Instead, // KTabBar just seems to go straight to slotTabDragInitiate. Q_UNUSED(e); accept = true; } void KTechlab::slotTabDragInitiate( TQWidget *widget ) { ViewContainer *viewContainer = dynamic_cast(widget); if (!viewContainer) return; TQDragObject *dragObject = new ViewContainerDrag(viewContainer); dragObject->drag(); } void KTechlab::slotTabReceivedDropEvent( TQDropEvent *e ) { if (!e) return; ViewContainer *viewContainerSource = dynamic_cast(e->source()); if (!viewContainerSource) { e->ignore(); return; } e->accept(true); viewContainerSource->duplicateViewContainer(); } void KTechlab::slotTabReceivedDropEvent( TQWidget *widget, TQDropEvent *e ) { if (!e) return; m_pContainerDropSource = dynamic_cast(e->source()); m_pContainerDropReceived = dynamic_cast(widget); if ( !m_pContainerDropSource || !m_pContainerDropReceived || (m_pContainerDropSource == m_pContainerDropReceived) ) { e->ignore(); return; } e->accept(true); TDEPopupMenu dropMenu; dropMenu.insertItem( TDEGlobal::iconLoader()->loadIcon( "goto", TDEIcon::Small ), i18n("&Insert Into"), 0 ); dropMenu.insertItem( TDEGlobal::iconLoader()->loadIcon( "edit-copy", TDEIcon::Small ), i18n("&Copy Into"), 1 ); dropMenu.insertSeparator(); dropMenu.insertItem( TDEGlobal::iconLoader()->loadIcon( "process-stop", TDEIcon::Small ), i18n("C&ancel"), 2 ); connect( &dropMenu, TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(slotDragContextActivated(int)) ); // dropMenu.exec(e->pos() + widget->pos() ); dropMenu.exec( TQCursor::pos() ); } void KTechlab::slotDragContextActivated( int id ) { if ( !m_pContainerDropSource || !m_pContainerDropReceived ) return; switch (id) { case 0: m_pContainerDropSource->copyViewContainerIntoExisting(m_pContainerDropReceived); m_pContainerDropSource->closeViewContainer(); break; case 1: m_pContainerDropSource->copyViewContainerIntoExisting(m_pContainerDropReceived); break; case 2: default: break; } } TDEAction * KTechlab::action( const TQString & name ) const { TDEAction * action = actionCollection()->action(name.utf8()); if ( !action ) kdError() << k_funcinfo << "No such action: " << name << endl; return action; } void KTechlab::saveProperties( TDEConfig *conf ) { // Dumbass TDEMainWindow - can't handle my width/height correctly. Whoever thought of the "+1" hack anyway?! conf->setGroup("UI"); conf->writeEntry( "Width", width() ); conf->writeEntry( "Height", height() ); conf->writeEntry( "WinState", KWin::windowInfo( winId(), NET::WMState ).state() ); #ifndef NO_GPSIM SymbolViewer::self()->saveProperties( conf ); #endif if ( ProjectManager::self()->currentProject() ) { conf->setGroup("Project"); conf->writePathEntry( "Open", ProjectManager::self()->currentProject()->url().prettyURL() ); } else conf->deleteGroup("Project"); //BEGIN Open Views State // Remvoe old entries describing the save state - we don't want a horrible mish-mash of saved states const TQStringList groupList = conf->groupList(); const TQStringList::const_iterator groupListEnd = groupList.end(); for ( TQStringList::const_iterator it = groupList.begin(); it != groupListEnd; ++it ) { if ( (*it).startsWith("ViewContainer") ) conf->deleteGroup(*it); } uint viewContainerId = 1; const ViewContainerList::iterator vcEnd = m_viewContainerList.end(); for ( ViewContainerList::iterator it = m_viewContainerList.begin(); it != vcEnd; ++it ) { if ( !(*it) || !(*it)->canSaveUsefulStateInfo() ) continue; // To make sure the ViewContainers are restored in the right order, we must create them in alphabetical order, // as TDEConfig stores them as such... const TQString id = TQString::number(viewContainerId++).rightJustify( 4, '0' ); conf->setGroup( "ViewContainer " + id ); (*it)->saveState(conf); } //END Open Views State saveSession( conf, "KateMDI" ); // Piss off TDEMainWindow conf->setGroup("KateMDI"); int scnum = TQApplication::desktop()->screenNumber(parentWidget()); TQRect desk = TQApplication::desktop()->screenGeometry(scnum); conf->deleteEntry( TQString::fromLatin1("Width %1").arg(desk.width()) ); conf->deleteEntry( TQString::fromLatin1("Height %1").arg(desk.height()) ); conf->sync(); } void KTechlab::readProperties( TDEConfig *conf ) { startRestore( conf, "KateMDI" ); m_recentFiles->loadEntries(); m_recentProjects->loadEntries(); //BEGIN Restore Open Views if ( KTLConfig::restoreDocumentsOnStartup() ) { // If we have a lot of views open from last time, then opening them will take a long time. // So we want to enter the qt event loop to finish drawing the window et al before adding the views. tqApp->processEvents(); const TQStringList groupList = conf->groupList(); const TQStringList::const_iterator groupListEnd = groupList.end(); for ( TQStringList::const_iterator it = groupList.begin(); it != groupListEnd; ++it ) { if ( (*it).startsWith("ViewContainer") ) { ViewContainer *viewContainer = new ViewContainer( *it, this ); conf->setGroup(*it); viewContainer->restoreState( conf, *it ); addWindow( viewContainer ); } } } //END Restore Open Views conf->setGroup("Project"); if ( conf->readPathEntry("Open") != TQString() ) ProjectManager::self()->slotOpenProject( KURL( conf->readPathEntry("Open") ) ); #ifndef NO_GPSIM SymbolViewer::self()->readProperties( conf ); #endif finishRestore(); // Dumbass TDEMainWindow - can't handle my width/height correctly. Whoever thought of the "+1" hack anyway?! conf->setGroup("UI"); resize( conf->readNumEntry( "Width", 800 ), conf->readNumEntry( "Height", 500 ) ); KWin::setState( winId(), conf->readLongNumEntry( "WinState", NET::Max ) ); } void KTechlab::dragEnterEvent(TQDragEnterEvent *event) { // accept uri drops only event->accept(KURLDrag::canDecode(event)); } void KTechlab::dropEvent(TQDropEvent *event) { // this is a very simplistic implementation of a drop event. we // will only accept a dropped URL. the TQt dnd code can do *much* // much more, so please read the docs there KURL::List urls; // see if we can decode a URI.. if not, just ignore it if (KURLDrag::decode(event, urls) && !urls.isEmpty()) { // okay, we have a URI.. process it const KURL &url = urls.first(); // load in the file load(url); } } void KTechlab::slotOptionsShowStatusbar() { // this is all very cut and paste code for showing/hiding the // statusbar if (m_statusbarAction->isChecked()) statusBar()->show(); else statusBar()->hide(); } void KTechlab::slotOptionsConfigureKeys() { // KKeyDialog::configureKeys(actionCollection(), "ktechlabui.rc"); KKeyDialog::configure( actionCollection(), this, true ); } void KTechlab::slotOptionsConfigureToolbars() { KEditToolbar *dlg = new KEditToolbar(guiFactory()); if (dlg->exec()) { createShellGUI( false ); createShellGUI( true ); } delete dlg; } void KTechlab::slotOptionsPreferences() { // An instance of your dialog could be already created and could be cached, // in which case you want to display the cached dialog instead of creating // another one if ( TDEConfigDialog::showDialog( "settings" ) ) return; // TDEConfigDialog didn't find an instance of this dialog, so lets create it: SettingsDlg* dialog = new SettingsDlg( this, "settings", KTLConfig::self() ); // User edited the configuration - update your local copies of the // configuration data connect( dialog, TQT_SIGNAL(settingsChanged()), TQT_TQOBJECT(this), TQT_SLOT(slotUpdateConfiguration()) ); dialog->show(); } void KTechlab::slotUpdateConfiguration() { emit configurationChanged(); } void KTechlab::slotChangeStatusbar( const TQString & text ) { // Avoid flicker by repeatedly displaying the same message, as TQStatusBar does not check for this if ( m_lastStatusBarMessage == text ) return; statusBar()->message(text); m_lastStatusBarMessage = text; } void KTechlab::slotTabContext( TQWidget* widget,const TQPoint & pos ) { // Shamelessly stolen from KDevelop... TDEPopupMenu * tabMenu = new TDEPopupMenu; tabMenu->insertTitle( (dynamic_cast(widget))->caption() ); //Find the document on whose tab the user clicked m_pContextMenuContainer = 0l; m_viewContainerList.remove((ViewContainer*)0l); const ViewContainerList::iterator vcEnd = m_viewContainerList.end(); for ( ViewContainerList::iterator it = m_viewContainerList.begin(); it != vcEnd; ++it ) { ViewContainer * viewContainer = *it; if ( viewContainer == widget ) { m_pContextMenuContainer = viewContainer; tabMenu->insertItem( i18n("Close"), 0 ); View *view = (viewContainer->viewCount() == 1) ? viewContainer->activeView() : 0l; if ( view && view->document()->isModified() ) tabMenu->insertItem( i18n("Save"), 1 ); if ( view && !view->document()->url().isEmpty() ) tabMenu->insertItem( i18n("Reload"), 2 ); if ( m_viewContainerList.count() > 1 ) tabMenu->insertItem( i18n("Close All Others"), 4 ); } } connect( tabMenu, TQT_SIGNAL( activated(int) ), TQT_TQOBJECT(this), TQT_SLOT(slotTabContextActivated(int)) ); tabMenu->exec(pos); delete tabMenu; } void KTechlab::slotTabContextActivated( int id ) { // Shamelessly stolen from KDevelop... if( !m_pContextMenuContainer ) return; View *view = m_pContextMenuContainer->activeView(); if (!view) return; TQGuardedPtr document = view->document(); switch(id) { case 0: { m_pContextMenuContainer->closeViewContainer(); break; } case 1: document->fileSave(); break; case 2: { KURL url = document->url(); if ( document->fileClose() ) { delete document; DocManager::self()->openURL(url); } break; } case 4: { const ViewContainerList::iterator vcEnd = m_viewContainerList.end(); for ( ViewContainerList::iterator it = m_viewContainerList.begin(); it != vcEnd; ++it ) { ViewContainer *viewContainer = *it; if ( viewContainer && viewContainer != m_pContextMenuContainer ) { if ( !viewContainer->closeViewContainer() ) return; } } break; } default: break; } } void KTechlab::slotFileNewAssembly() { TextDocument *document = DocManager::self()->createTextDocument(); if (document) document->slotInitLanguage( TextDocument::ct_asm ); } void KTechlab::slotFileNewMicrobe() { TextDocument *document = DocManager::self()->createTextDocument(); if (document) document->slotInitLanguage( TextDocument::ct_microbe ); } void KTechlab::slotFileNewC() { TextDocument *document = DocManager::self()->createTextDocument(); if (document) document->slotInitLanguage( TextDocument::ct_c ); } void KTechlab::slotFileNewCircuit() { DocManager::self()->createCircuitDocument(); } void KTechlab::slotFileNewFlowCode() { slotFileNew(); } void KTechlab::slotFileNewMechanics() { DocManager::self()->createMechanicsDocument(); } void KTechlab::slotFileNew() { NewFileDlg *newFileDlg = new NewFileDlg(this); newFileDlg->exec(); bool addToProject = newFileDlg->addToProject(); bool accepted = newFileDlg->accepted(); int finalType = newFileDlg->fileType(); TQString microID = newFileDlg->microID(); int codeType = newFileDlg->codeType(); delete newFileDlg; if (!accepted) return; Document *created = 0l; if ( finalType == Document::dt_circuit ) created = DocManager::self()->createCircuitDocument(); else if ( finalType == Document::dt_flowcode ) { FlowCodeDocument * fcd = DocManager::self()->createFlowCodeDocument(); fcd->setPicType(microID); created = fcd; } else if ( finalType == Document::dt_mechanics ) created = DocManager::self()->createMechanicsDocument(); else { // Presumably a text document TextDocument * textDocument = DocManager::self()->createTextDocument(); if (textDocument) textDocument->slotInitLanguage( (TextDocument::CodeType)codeType ); created = textDocument; } if ( created && addToProject ) created->setAddToProjectOnSave(true); } void KTechlab::slotFileOpen() { // this slot is called whenever the File->Open menu is selected, // the Open shortcut is pressed (usually CTRL+O) or the Open toolbar // button is clicked // standard filedialog KURL::List urls = getFileURLs(); const KURL::List::iterator end = urls.end(); for ( KURL::List::iterator it = urls.begin(); it != end; ++ it) load(*it); } void KTechlab::addRecentFile( const KURL &url ) { m_recentFiles->addURL( url ); emit recentFileAdded(url); } KURL::List KTechlab::getFileURLs() { return KFileDialog::getOpenURLs( TQString(), "*|All Files\n" "*.asm *.src *.inc|Assembly Code (*.asm, *.src, *.inc)\n" "*.hex|Intel Hex (*.hex)\n" "*.circuit|Circuit (*.circuit)\n" "*.flowcode|FlowCode (*.flowcode)\n" "*.basic *.microbe|Microbe (*.microbe, *.basic)\n" "*.mechanics|Mechanics (*.mechanics)\n", 0L, i18n("Open Location") ); } void KTechlab::slotDocModifiedChanged() { //BEGIN Set tab icons TDEIconLoader *loader = TDEGlobal::iconLoader(); const ViewContainerList::iterator vcEnd = m_viewContainerList.end(); for ( ViewContainerList::iterator it = m_viewContainerList.begin(); it != vcEnd; ++it ) { ViewContainer * vc = *it; if ( !vc || !vc->activeView() || !vc->activeView()->document() ) continue; TQString iconName; if ( vc->activeView()->document()->isModified() ) iconName = "document-save"; else switch ( vc->activeView()->document()->type() ) { case Document::dt_circuit: iconName = "ktechlab_circuit"; break; case Document::dt_flowcode: iconName = "ktechlab_flowcode"; break; case Document::dt_mechanics: iconName = "ktechlab_mechanics"; break; case Document::dt_text: iconName = "text-plain"; break; case Document::dt_pinMapEditor: break; case Document::dt_none: iconName = "unknown"; break; } tabWidget()->setTabIconSet( vc, loader->loadIcon( iconName, TDEIcon::Small ) ); } //END Set tab icons } void KTechlab::requestUpdateCaptions() { m_pUpdateCaptionsTimer->start( 0, true ); } void KTechlab::slotUpdateCaptions() { //BEGIN Set KTechlab caption Document *document = DocManager::self()->getFocusedDocument(); TQString newCaption; if ( document ) { KURL url = document->url(); if ( url.isEmpty() ) newCaption = document->caption(); else { if ( url.isLocalFile() && url.ref().isNull() && url.query().isNull() ) newCaption = url.path(); else newCaption = url.prettyURL(); } } else newCaption = ""; if (newCaption != caption().remove(" - KTechlab")) setCaption(newCaption); //END Set KTechlab caption //BEGIN Set tab captions emit needUpdateCaptions(); if ( document && document->activeView() && document->activeView()->viewContainer() ) { document->activeView()->viewContainer()->updateCaption(); } //END Set tab captions } void KTechlab::slotDocUndoRedoChanged() { Document *document = DocManager::self()->getFocusedDocument(); if (!document) return; action("edit_undo")->setEnabled( document->isUndoAvailable() ); action("edit_redo")->setEnabled( document->isRedoAvailable() ); } void KTechlab::slotFileSave() { Document *document = DocManager::self()->getFocusedDocument(); if (document) document->fileSave(); } void KTechlab::slotFileSaveAs() { Document *document = DocManager::self()->getFocusedDocument(); if (document) document->fileSaveAs(); } void KTechlab::slotFilePrint() { Document *document = DocManager::self()->getFocusedDocument(); if (document) document->print(); } bool KTechlab::queryClose() { saveProperties( TDEGlobal::config() ); if ( DocManager::self()->closeAll() && ProjectManager::self()->slotCloseProject() ) { ViewContainerList::iterator end = m_viewContainerList.end(); for ( ViewContainerList::iterator it = m_viewContainerList.begin(); it != end; ++it ) { if ( *it ) (*it)->setKTechlabDeleted(); } return true; } return false; } void KTechlab::slotFileQuit() { // close the first window, the list makes the next one the first again. // This ensures that queryClose() is called on each window to ask for closing TDEMainWindow* w; if(memberList) { for( w=memberList->first(); w!=0; w=memberList->next() ) { // only close the window if the closeEvent is accepted. If the user presses Cancel on the saveModified() dialog, // the window and the application stay open. if( !w->close() ) break; } } slotChangeStatusbar( i18n("Exiting...") ); } void KTechlab::slotEditUndo() { Document *document = DocManager::self()->getFocusedDocument(); if (document) document->undo(); } void KTechlab::slotEditRedo() { Document *document = DocManager::self()->getFocusedDocument(); if (document) document->redo(); } void KTechlab::slotEditCut() { Document *document = DocManager::self()->getFocusedDocument(); if (document) document->cut(); } void KTechlab::slotEditCopy() { Document *document = DocManager::self()->getFocusedDocument(); if (document) document->copy(); } void KTechlab::slotEditPaste() { Document *document = DocManager::self()->getFocusedDocument(); if (document) document->paste(); } void KTechlab::slotViewContainerClose() { if (m_pFocusedContainer) m_pFocusedContainer->closeViewContainer(); } void KTechlab::slotViewClose() { View *view = DocManager::self()->getFocusedView(); if (view) view->closeView(); } void KTechlab::slotViewSplitLeftRight() { View *view = DocManager::self()->getFocusedView(); if (!view) return; ViewContainer *vc = view->viewContainer(); uint vaId = vc->createViewArea( view->viewAreaId(), ViewArea::Right ); view->document()->createView( vc, vaId ); } void KTechlab::slotViewSplitTopBottom() { View *view = DocManager::self()->getFocusedView(); if (!view) return; ViewContainer *vc = view->viewContainer(); uint vaId = vc->createViewArea( view->viewAreaId(), ViewArea::Bottom ); view->document()->createView( vc, vaId ); } #include "ktechlab.moc"