/*************************************************************************** * Copyright (C) 2003 by Martin Galpin * * martin@nemohackers.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. * ***************************************************************************/ #include "kuake.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kuakepushbutton.h" #include "kuakecustomsize.h" // Main constructor for this class. Embeds the KPart konsole into a KParts::MainWindow and // initialises any varibles needed for the class. Kuake::Kuake() : DCOPObject("KuakeIface"), KParts::MainWindow(0, "Kuake", WStyle_Customize|WStyle_NoBorder) { QWidget* tmp = QApplication::desktop(); screenWidth = tmp->width(); screenHeight = tmp->height(); setGeometry(0, 0, screenWidth, _BUTTON_SIZE); stack = new QWidgetStack(this); stack->hide(); KLibFactory *factory = 0; factory = KLibLoader::self()->factory("libkonsolepart"); part = 0L; if (factory) { part = static_cast(factory->create(this,"libkonsolepart", "KParts::ReadOnlyPart")); if (part) { KGlobal::locale()->insertCatalogue("konsole"); part->widget()->show(); part->setSelectable(true); stack->addWidget(part->widget()); connect(part, SIGNAL(destroyed()), this, SLOT(slotDestroyed())); } } pbResize = new KuakePushButton(this, "resize"); ctx = new KPopupMenu(this); actionCollection = new KActionCollection(this, "action"); //KAction* actPrefs = KStdAction::preferences(this, SLOT(slotPrefs()), actionCollection); ctxSizeRatio = new KPopupMenu(ctx); ctxSizeRatioFullID = ctxSizeRatio->insertItem("100%", this, SLOT(slotSizeRatioFull())); ctxSizeRatioHalfID = ctxSizeRatio->insertItem("50%", this, SLOT(slotSizeRatioHalf())); ctxSizeRatioThirdID = ctxSizeRatio->insertItem("33%", this, SLOT(slotSizeRatioThird())); ctxSizeRatioQuarterID = ctxSizeRatio->insertItem("25%", this, SLOT(slotSizeRatioQuarter())); ctxSizeRatioCustomID = ctxSizeRatio->insertItem("Custom...", this, SLOT(slotSizeRatioCustom())); ctxSizeRatioCheckedID = ctxSizeRatioFullID; ctxAlignment = new KPopupMenu(ctx); ctxAlignmentTopID = ctxAlignment->insertItem ("Top", this, SLOT(slotAlignmentTop())); ctxAlignmentBottomID = ctxAlignment->insertItem ("Bottom", this, SLOT(slotAlignmentBottom())); ctxAlignmentLeftID = ctxAlignment->insertItem ("Left", this, SLOT(slotAlignmentLeft())); ctxAlignmentRightID = ctxAlignment->insertItem ("Right", this, SLOT(slotAlignmentRight())); ctxAlignmentCheckedID = ctxAlignmentTopID; ctxAnimation = new KPopupMenu(ctx); ctxAnimationNoneID = ctxAnimation->insertItem ("None", this, SLOT(slotAnimationNone())); ctxAnimationSlowID = ctxAnimation->insertItem ("Slow", this, SLOT(slotAnimationSlow())); ctxAnimationMediumID = ctxAnimation->insertItem ("Medium", this, SLOT(slotAnimationMedium())); ctxAnimationFastID = ctxAnimation->insertItem ("Fast", this, SLOT(slotAnimationFast())); ctxAnimationCheckedID = ctxAnimationNoneID; ctx->insertItem("Si&ze", ctxSizeRatio); ctx->insertItem("&Alignment", ctxAlignment); ctx->insertItem("A&nimation", ctxAnimation); ctx->insertItem("Toggle key...", this, SLOT(slotToggleKeyDialog())); ctxToggleButtonID = ctx->insertItem("Toggle Button", this, SLOT(slotToggleButton())); //ctxEnableTabsID = ctx->insertItem("&Enable Tabs"); KAction* actAbout = KStdAction::aboutApp(this, SLOT(slotAbout()), actionCollection); KAction* actQuit = KStdAction::quit(this, SLOT(slotQuit()), actionCollection); ctx->insertSeparator(); actAbout->plug(ctx); actQuit->plug(ctx); KConfig conf("kuakerc"); //compact = conf.readBoolEntry("state", true); globalAccel = new KGlobalAccel(this); globalAccel->insert("ToggleState", i18n("Toggle State"), i18n("Toggles the state of Kuake"), ALT+Key_AsciiTilde, 0, this, SLOT(slotToggleKey())); globalAccel->readSettings(&conf); globalAccel->updateConnections(); // Correct calls to the window manager KWin::forceActiveWindow (winId()); KWin::setState (winId(), NET::StaysOnTop | NET::Sticky | NET::SkipTaskbar); KWin::setOnAllDesktops(winId(), true); oldActiveWindow = 0; kwinmodule = new KWinModule(this); readConfig(); changeState(true); //resizeKuake(); //emit slotChangeState(); show(); KStartupInfoId id; id.initId(kapp->startupId()); KStartupInfo::sendFinish(id); } // --------------------------------------------------------------- // Kuake::~Kuake() { // Qt will handle the deletion of child widgets. } // --------------------------------------------------------------- // // Called by the DCOP client in order to change the state of Kuake. void Kuake::setKuakeState(int) { emit slotChangeState(); } // --------------------------------------------------------------- // // Simply calls the interface changing functions. void Kuake::slotChangeState() { changeState(false); } // --------------------------------------------------------------- // // Execute the toggle key void Kuake::slotToggleKey() { changeState(true); } // --------------------------------------------------------------- // // Changes the state of Kuake. When COMPACT is true the widget is minimal // and needs to show() the STACK child and make this window active. void Kuake::changeState(bool handleOldActiveWindow) { if (compact) { if(handleOldActiveWindow) oldActiveWindow = kwinmodule->activeWindow(); stack->show(); raise(); setActiveWindow(); resizeKuake(); compact = activeWindow = false; } else { resizeKuake(); stack->hide(); compact = activeWindow = true; if(handleOldActiveWindow && oldActiveWindow) KWin::forceActiveWindow(oldActiveWindow); } } // --------------------------------------------------------------- // // This method resizes Kuake to the ORIENTATION and SIZE varibles set by // the user. It will resize Kuake and change it's state. void Kuake::resizeKuake() { if (compact) // Enlarge { //int top = (toggleButton) ? -10 : 0; switch (alignment) { case _ALIGN_TOP: for(int s = 0; s <= animation_steps; s++) { int i = animate(0, size, s, animation_steps); setGeometry(0, 0, screenWidth, i); } pbResize->setGeometry(0, size - _BUTTON_SIZE, screenWidth, _BUTTON_SIZE); stack->setGeometry(0, 0, screenWidth, size - _BUTTON_SIZE); KWin::setStrut(winId(), 0, 0, (toggleButton)?_BUTTON_SIZE:0, 0); break; case _ALIGN_BOTTOM: for(int s = 0; s <= animation_steps; s++) { int i = animate(0, size, s, animation_steps); setGeometry(0, screenHeight - i, screenWidth, i); } pbResize->setGeometry(0, 0, screenWidth, _BUTTON_SIZE); stack->setGeometry(0, _BUTTON_SIZE, screenWidth, size - _BUTTON_SIZE); KWin::setStrut(winId(), 0, 0, 0, (toggleButton)?_BUTTON_SIZE:0); break; case _ALIGN_LEFT: for(int s = 0; s <= animation_steps; s++) { int i = animate(0, size, s, animation_steps); setGeometry(0, 0, i, screenHeight); } pbResize->setGeometry(size - _BUTTON_SIZE, 0, _BUTTON_SIZE, screenHeight); stack->setGeometry(0, 0, size - _BUTTON_SIZE, screenHeight); KWin::setStrut(winId(), (toggleButton)?_BUTTON_SIZE:0, 0, 0, 0); break; case _ALIGN_RIGHT: for(int s = 0; s <= animation_steps; s++) { int i = animate(0, size, s, animation_steps); setGeometry(screenWidth - i, 0, i, screenHeight); } pbResize->setGeometry(0, 0, _BUTTON_SIZE, screenHeight); stack->setGeometry(_BUTTON_SIZE, 0, size, screenHeight); KWin::setStrut(winId(), 0, (toggleButton)?_BUTTON_SIZE:0, 0, 0); break; } } else // Compact { switch (alignment) { case _ALIGN_TOP: for(int s = 0; s <= animation_steps; s++) { int i = animate(size, _BUTTON_SIZE, s, animation_steps); setGeometry(0, (toggleButton)?0:-_BUTTON_SIZE, screenWidth, i); } pbResize->setGeometry(0, 0, screenWidth, _BUTTON_SIZE); KWin::setStrut(winId(), 0, 0, (toggleButton)?_BUTTON_SIZE:0, 0); break; case _ALIGN_BOTTOM: for(int s = 0; s <= animation_steps; s++) { int i = animate(size, _BUTTON_SIZE, s, animation_steps); setGeometry(0, (toggleButton)?screenHeight-i:(screenHeight-i)+_BUTTON_SIZE, screenWidth, i); } pbResize->setGeometry(0, 0, screenWidth, _BUTTON_SIZE); KWin::setStrut(winId(), 0, 0, 0, (toggleButton)?_BUTTON_SIZE:0); break; case _ALIGN_LEFT: for(int s = 0; s <= animation_steps; s++) { int i = animate(size, _BUTTON_SIZE, s, animation_steps); setGeometry((toggleButton)?0:-_BUTTON_SIZE, 0, i, screenHeight); } pbResize->setGeometry(0, 0, _BUTTON_SIZE, screenHeight); KWin::setStrut(winId(), (toggleButton)?_BUTTON_SIZE:0, 0, 0, 0); break; case _ALIGN_RIGHT: for(int s = 0; s <= animation_steps; s++) { int i = animate(size, _BUTTON_SIZE, s, animation_steps); setGeometry((toggleButton)?(screenWidth-i):(screenWidth-i)+_BUTTON_SIZE, 0, i, screenHeight); } pbResize->setGeometry(0, 0, _BUTTON_SIZE, screenHeight); KWin::setStrut(winId(), 0, (toggleButton)?_BUTTON_SIZE:0, 0, 0); break; } } } // --------------------------------------------------------------- // // This method resizes Kuake to the ORIENTATION and SIZE varibles set by // the user. It will resize Kuake without changing the state, thus should // be used when changing is "on the fly". void Kuake::resizeKeepingState() { if (!compact) { switch (alignment) { case _ALIGN_TOP: setGeometry(0, 0, screenWidth, size); pbResize->setGeometry(0, size - _BUTTON_SIZE, screenWidth, _BUTTON_SIZE); stack->setGeometry(0, 0, screenWidth, size - _BUTTON_SIZE); KWin::setStrut(winId(), 0, 0, _BUTTON_SIZE, 0); break; case _ALIGN_BOTTOM: setGeometry(0, screenHeight - size, screenWidth, size); pbResize->setGeometry(0, 0, screenWidth, _BUTTON_SIZE); stack->setGeometry(0, _BUTTON_SIZE, screenWidth, size - _BUTTON_SIZE); KWin::setStrut(winId(), 0, 0, 0, _BUTTON_SIZE); break; case _ALIGN_LEFT: setGeometry(0, 0, size, screenHeight); pbResize->setGeometry(size - _BUTTON_SIZE, 0, _BUTTON_SIZE, screenHeight); stack->setGeometry(0, 0, size - _BUTTON_SIZE, screenHeight); KWin::setStrut(winId(), _BUTTON_SIZE, 0, 0, 0); break; case _ALIGN_RIGHT: setGeometry(screenWidth - size, 0, size, screenHeight); pbResize->setGeometry(0, 0, _BUTTON_SIZE, screenHeight); stack->setGeometry(_BUTTON_SIZE, 0, size, screenHeight); KWin::setStrut(winId(), 0, _BUTTON_SIZE, 0, 0); break; } } else { switch (alignment) { case _ALIGN_TOP: setGeometry(0, (toggleButton)?0:-_BUTTON_SIZE, screenWidth, _BUTTON_SIZE); pbResize->setGeometry(0, 0, screenWidth, _BUTTON_SIZE); KWin::setStrut(winId(), 0, 0, (toggleButton)?_BUTTON_SIZE:0, 0); break; case _ALIGN_BOTTOM: setGeometry(0, (toggleButton)?(screenHeight-_BUTTON_SIZE):(screenHeight-_BUTTON_SIZE)+_BUTTON_SIZE, screenWidth, _BUTTON_SIZE); pbResize->setGeometry(0, 0, screenWidth, _BUTTON_SIZE); KWin::setStrut(winId(), 0, 0, 0, (toggleButton)?_BUTTON_SIZE:0); break; case _ALIGN_LEFT: setGeometry(0, 0, (toggleButton)?0:-_BUTTON_SIZE, screenHeight); pbResize->setGeometry(0, 0, _BUTTON_SIZE, screenHeight); KWin::setStrut(winId(), (toggleButton)?_BUTTON_SIZE:0, 0, 0, 0); break; case _ALIGN_RIGHT: setGeometry((toggleButton)?(screenWidth-_BUTTON_SIZE):(screenWidth-_BUTTON_SIZE)+_BUTTON_SIZE, 0, _BUTTON_SIZE, screenHeight); pbResize->setGeometry(0, 0, _BUTTON_SIZE, screenHeight); KWin::setStrut(winId(), 0, (toggleButton)?_BUTTON_SIZE:0, 0, 0); break; } } } // --------------------------------------------------------------- // // This method is an overloaded function which changes the state of Kuake when // the user selects a different window. void Kuake::windowActivationChange(bool) { if (!isActiveWindow() && !activeWindow) { activeWindow = true; emit slotChangeState(); } } // --------------------------------------------------------------- // // This method reads the saved settings of alignment and size. It should only be // called when the instance of this class is created as all varibles are stored as // members to this class. void Kuake::readConfig() { KConfig conf ("kuakerc"); sizeRatio = conf.readNumEntry("size_ratio", _SIZE_RATIO_THIRD); switch (sizeRatio) { case _SIZE_RATIO_FULL: emit slotSizeRatioFull(); break; case _SIZE_RATIO_HALF: emit slotSizeRatioHalf(); break; case _SIZE_RATIO_THIRD: emit slotSizeRatioThird(); break; case _SIZE_RATIO_QUARTER: emit slotSizeRatioQuarter(); break; default: if(sizeRatio > _SIZE_RATIO_FULL) sizeRatio = _SIZE_RATIO_FULL; else if(sizeRatio < _SIZE_RATIO_MIN) sizeRatio = _SIZE_RATIO_MIN; emit slotSizeRatioCustom(); break; } alignment = conf.readNumEntry ("alignment", _ALIGN_BOTTOM); switch (alignment) { case _ALIGN_TOP: emit slotAlignmentTop(); break; case _ALIGN_BOTTOM: emit slotAlignmentTop(); break; case _ALIGN_LEFT: emit slotAlignmentLeft(); break; case _ALIGN_RIGHT: emit slotAlignmentRight(); break; default: // _ALIGN_BOTTOM: emit slotAlignmentBottom(); break; } animation_steps = conf.readNumEntry("animation", _ANIMATION_MEDIUM); switch (animation_steps) { case _ANIMATION_NONE: emit slotAnimationNone(); break; case _ANIMATION_SLOW: emit slotAnimationSlow(); break; case _ANIMATION_MEDIUM: emit slotAnimationMedium(); break; case _ANIMATION_FAST: emit slotAnimationFast(); break; } toggleButton = conf.readBoolEntry("toggleButton", true); ctx->setItemChecked(ctxToggleButtonID, toggleButton); } // --------------------------------------------------------------- // // This slot is emitted when the user selects "Quit" from the konsoles context menu. void Kuake::slotDestroyed () { emit slotQuit(); } // --------------------------------------------------------------- // // Self explainitry. void Kuake::slotAbout() { KAboutApplication* about = new KAboutApplication(this); about->show(); } // --------------------------------------------------------------- // // Saves the state of Kuake so that the next time we start up, it's restored. void Kuake::slotQuit() { KConfig conf("kuakerc"); if (compact) { conf.writeEntry("state", "false"); } else { conf.writeEntry("state", "true"); } qApp->quit(); } // --------------------------------------------------------------- // // These methods are called by the respective slot* methods and contain // the code they use in common. Essentially, This works around the lack of // parameters for SLOTs. void Kuake::setSizeRatio(int p_sizeRatio, int ctxID) { KConfig conf ("kuakerc"); conf.writeEntry("size_ratio", p_sizeRatio); sizeRatio = p_sizeRatio; size = calcSize(); ctxSizeRatio->setItemChecked(ctxSizeRatioCheckedID, false); ctxSizeRatioCheckedID = ctxID; ctxSizeRatio->setItemChecked(ctxSizeRatioCheckedID, true); resizeKeepingState(); } // --------------------------------------------------------------- // void Kuake::setAlignment(int p_alignment, int ctxID) { KConfig conf ("kuakerc"); conf.writeEntry("alignment", p_alignment); alignment = p_alignment; ctxAlignment->setItemChecked(ctxAlignmentCheckedID, false); ctxAlignmentCheckedID = ctxID; ctxAlignment->setItemChecked(ctxAlignmentCheckedID, true); resizeKeepingState(); } // --------------------------------------------------------------- // void Kuake::setAnimation(int p_animation_steps, int ctxID) { KConfig conf ("kuakerc"); conf.writeEntry("animation", p_animation_steps); animation_steps = p_animation_steps; ctxAnimation->setItemChecked(ctxAnimationCheckedID, false); ctxAnimationCheckedID = ctxID; ctxAnimation->setItemChecked(ctxAnimationCheckedID, true); } // --------------------------------------------------------------- // // --------------------------------------------------------------- // // The following methods are all emitted when the appropriate item is selected // in the context menu or when this setting is read from the config file. void Kuake::slotSizeRatioFull() { setSizeRatio(_SIZE_RATIO_FULL, ctxSizeRatioFullID); } // --------------------------------------------------------------- // void Kuake::slotSizeRatioHalf() { setSizeRatio(_SIZE_RATIO_HALF, ctxSizeRatioHalfID); } // --------------------------------------------------------------- // void Kuake::slotSizeRatioThird() { setSizeRatio(_SIZE_RATIO_THIRD, ctxSizeRatioThirdID); } void Kuake::slotSizeRatioQuarter() { setSizeRatio(_SIZE_RATIO_QUARTER, ctxSizeRatioQuarterID); } // --------------------------------------------------------------- // void Kuake::slotSizeRatioCustom() { new KuakeCustomSize(this, 0, &sizeRatio); } // --------------------------------------------------------------- // void Kuake::slotCustomSizeOkClicked() { setSizeRatio(sizeRatio, ctxSizeRatioCustomID); // sizeRatio contains the new custom value at this point } // --------------------------------------------------------------- // void Kuake::slotAlignmentTop() { setAlignment(_ALIGN_TOP, ctxAlignmentTopID); } // --------------------------------------------------------------- // void Kuake::slotAlignmentBottom() { setAlignment(_ALIGN_BOTTOM, ctxAlignmentBottomID); } // --------------------------------------------------------------- // void Kuake::slotAlignmentLeft() { setAlignment(_ALIGN_LEFT, ctxAlignmentLeftID); } // --------------------------------------------------------------- // void Kuake::slotAlignmentRight() { setAlignment(_ALIGN_RIGHT, ctxAlignmentRightID); } // --------------------------------------------------------------- // void Kuake::slotAnimationNone() { setAnimation(_ANIMATION_NONE, ctxAnimationNoneID); } // --------------------------------------------------------------- // void Kuake::slotAnimationSlow() { setAnimation(_ANIMATION_SLOW, ctxAnimationSlowID); } // --------------------------------------------------------------- // void Kuake::slotAnimationMedium() { setAnimation(_ANIMATION_MEDIUM, ctxAnimationMediumID); } // --------------------------------------------------------------- // void Kuake::slotAnimationFast() { setAnimation(_ANIMATION_FAST, ctxAnimationFastID); } // --------------------------------------------------------------- // // Show the KKey dialog for configuring the toggle key void Kuake::slotToggleKeyDialog() { KKeyDialog::configure(globalAccel); KConfig conf ("kuakerc"); globalAccel->updateConnections(); globalAccel->writeSettings(&conf); } // --------------------------------------------------------------- // // Show/Hide the toggle button void Kuake::slotToggleButton() { (toggleButton) ? toggleButton = false : toggleButton = true; KConfig conf("kuakerc"); conf.writeEntry("toggleButton", toggleButton); ctx->setItemChecked(ctxToggleButtonID, toggleButton); resizeKeepingState(); } // --------------------------------------------------------------- // // Calculate a value between start and end depending on the current // animation step. int Kuake::animate(int start, int end, int current_step, int total_steps) { return (int) (start + (end - start) * sin((M_PI / 2) * ((double) current_step) / ((double) total_steps)) ); } // Return the size in pixels based on screen dimensions, sizeRatio and alignment. int Kuake::calcSize() { return ((alignment == _ALIGN_TOP) || (alignment == _ALIGN_BOTTOM)) ? (screenHeight * sizeRatio / _SIZE_RATIO_FULL) : (screenWidth * sizeRatio / _SIZE_RATIO_FULL); } #include "kuake.moc"