You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kftpgrabber/kftpgrabber/src/widgets/sidebar.cpp

394 lines
11 KiB

/*
* This file is part of the KFTPGrabber project
*
* Copyright (C) 2003-2005 by the KFTPGrabber developers
* Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.net>
* Copyright (C) 2004-2005 Max Howell <max.howell@methylblue.com>
*
* 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
* is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
* NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
#include "misc.h"
#include "sidebar.h"
#include "multitabbar.h"
#include <tdeapplication.h>
#include <tdeconfig.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tqcursor.h>
#include <tqpainter.h>
#include <tqsignalmapper.h>
#include <tqstyle.h>
namespace KFTPWidgets {
class Splitter : public TQWidget {
public:
Splitter(Sidebar *w)
: TQWidget(w, "divider"),
m_position(w->m_position)
{
if (m_position == Sidebar::Left)
setCursor(TQCursor(SplitHCursor));
else
setCursor(TQCursor(SplitVCursor));
styleChange(style());
}
virtual void paintEvent(TQPaintEvent*)
{
TQPainter p(this);
parentWidget()->style().drawPrimitive(TQStyle::PE_Splitter, &p, rect(), colorGroup(), m_position == Sidebar::Left ? TQStyle::Style_Horizontal : 0);
}
virtual void styleChange(TQStyle&)
{
if (m_position == Sidebar::Left)
setFixedWidth(style().pixelMetric(TQStyle::PM_SplitterWidth, this));
else
setFixedHeight(style().pixelMetric(TQStyle::PM_SplitterWidth, this));
}
virtual void mouseMoveEvent(TQMouseEvent *e)
{
static_cast<Sidebar*>(parent())->mouseMovedOverSplitter(e);
}
private:
Sidebar::Position m_position;
};
Sidebar::Sidebar(TQWidget *parent, Position position)
: TQWidget(parent, "Sidebar"),
m_position(position),
m_divider(new KFTPWidgets::Splitter(this)),
m_content(new TQVBox(this)),
m_tabBar(new MultiTabBar(position == Left ? MultiTabBar::Vertical : MultiTabBar::Horizontal, this)),
m_sidebarBox(new TQWidget(this)),
m_currentIndex(-1),
m_lastIndex(-1),
m_mapper(new TQSignalMapper(this))
{
m_tabBar->setStyle(MultiTabBar::AMAROK);
m_tabBar->setPosition(m_position == Left ? MultiTabBar::Left : MultiTabBar::Bottom);
m_tabBar->showActiveTabTexts(true);
if (m_position == Left) {
m_pos = m_tabBar->sizeHint().width() + 5;
m_tabBar->setFixedWidth(m_pos);
m_tabBar->move(0, 3);
TQVBoxLayout *layout = new TQVBoxLayout(m_sidebarBox);
layout->addSpacing(3);
layout->setAutoAdd(true);
m_sidebarBox->move(m_pos, 0);
m_sidebarBox->hide();
m_divider->hide();
m_content->setSpacing(1);
} else {
m_pos = m_tabBar->sizeHint().height() + 5;
m_tabBar->setFixedHeight(m_pos);
TQVBoxLayout *layout = new TQVBoxLayout(m_sidebarBox);
layout->setAutoAdd(true);
m_sidebarBox->hide();
m_divider->hide();
m_content->setSpacing(1);
}
connect(m_mapper, TQ_SIGNAL(mapped(int)), TQ_SLOT(showHideSidebar(int)));
}
void Sidebar::setVisible(bool visible)
{
if (m_position == Left) {
m_pos = m_tabBar->sizeHint().width() + 5;
m_tabBar->setFixedWidth(visible ? m_pos : 0);
} else {
m_pos = m_tabBar->sizeHint().height() + 5;
m_tabBar->setFixedHeight(visible ? m_pos : 0);
}
if (m_currentIndex != -1)
showHideSidebar(m_currentIndex);
if (visible)
m_tabBar->show();
else
m_tabBar->hide();
adjustWidgetSizes();
}
Sidebar::~Sidebar()
{
TDEConfig *config;
// Save the currently selected sidebar
if (m_position == Left) {
config = KFTPGrabberBase::config(TQString("Sidebar_%1").arg("Left"));
} else {
config = KFTPGrabberBase::config(TQString("Sidebar_%1").arg("Bottom"));
}
if (m_currentIndex != -1) {
config->writeEntry("CurrentSidebar", currentSidebar()->name());
} else {
config->writeEntry("CurrentSidebar", TQString::null);
}
if (m_position == Left) {
config->writeEntry("Size", m_sidebarBox->width());
} else {
config->writeEntry("Size", m_sidebarBox->height());
}
}
void Sidebar::polish()
{
TQWidget::polish();
TDEConfig *config = KFTPGrabberBase::config(TQString("Sidebar_%1").arg(m_position == Left ? "Left" : "Bottom"));
const int index = indexForName(config->readEntry("CurrentSidebar"));
if (m_position == Left) {
uint M = 0;
for (SidebarList::ConstIterator it = m_sidebars.begin(), end = m_sidebars.end(); it != end; ++it) {
const uint m = (*it)->minimumWidth();
if (m > M) M = m;
}
const int width = config->readNumEntry("Size", sidebar(index)->sizeHint().width());
if (M > 250) {
M = 250;
}
m_sidebarBox->setMinimumWidth(M);
m_sidebarBox->resize(width, height());
} else {
uint M = 0;
for (SidebarList::ConstIterator it = m_sidebars.begin(), end = m_sidebars.end(); it != end; ++it) {
const uint m = (*it)->minimumHeight();
if (m > M) M = m;
}
const int height = config->readNumEntry("Size", sidebar(index)->height());
if (M > 250) {
M = 250;
}
m_sidebarBox->setMinimumHeight(M);
m_sidebarBox->resize(width(), height);
}
// If any sidebar should be open, open it
if (index != -1)
showHideSidebar(index);
}
void Sidebar::adjustWidgetSizes()
{
if (m_position == Left) {
const uint w = width();
const uint h = height();
const uint mxW = maxSidebarWidth();
const uint p = (m_pos < mxW) ? m_pos : mxW;
const uint ppw = p + m_divider->width();
const uint tbw = m_tabBar->width();
m_divider->move(p, 0);
const uint offset = !m_divider->isHidden() ? ppw : tbw;
m_sidebarBox->resize(p - tbw, h);
m_content->setGeometry(offset, 0, w - offset, h);
} else {
const uint w = width();
const uint h = height();
const uint mxH = maxSidebarHeight();
const uint p = (m_pos < mxH) ? m_pos : mxH;
const uint pph = p + m_divider->height();
const uint tbh = m_tabBar->height();
m_divider->move(0, h - pph);
const uint offset = !m_divider->isHidden() ? pph : tbh;
m_sidebarBox->setGeometry(0, h - p, w, p - tbh);
m_content->setGeometry(0, 0, w, h - offset);
m_tabBar->move(0, h - tbh);
}
}
void Sidebar::mouseMovedOverSplitter(TQMouseEvent *e)
{
const uint oldPos = m_pos;
uint newPos;
uint minPos;
uint maxPos;
if (m_position == Left) {
newPos = mapFromGlobal(e->globalPos()).x();
minPos = m_tabBar->width() + m_sidebarBox->minimumWidth();
maxPos = maxSidebarWidth();
} else {
newPos = height() - mapFromGlobal(e->globalPos()).y();
minPos = m_tabBar->height() + m_sidebarBox->minimumHeight();
maxPos = maxSidebarHeight();
}
if (newPos < minPos)
m_pos = minPos;
else if (newPos > maxPos)
m_pos = maxPos;
else
m_pos = newPos;
if (m_pos != oldPos)
adjustWidgetSizes();
}
bool Sidebar::event(TQEvent *e)
{
switch (e->type()) {
case TQEvent::LayoutHint: {
if (m_position == Left) {
setMinimumWidth(m_tabBar->minimumWidth() + m_divider->minimumWidth() + m_sidebarBox->width() + m_content->minimumWidth());
} else {
setMinimumHeight(m_tabBar->minimumHeight() + m_divider->minimumHeight() + m_sidebarBox->height() + m_content->minimumHeight());
}
break;
}
case TQEvent::Resize: {
if (m_position == Left) {
m_divider->resize(0, height());
m_tabBar->resize(0, height());
} else {
m_divider->resize(width(), 0);
m_tabBar->resize(width(), 0);
}
adjustWidgetSizes();
return true;
}
default: break;
}
return TQWidget::event(e);
}
void Sidebar::addSidebar(TQWidget *widget, const TQString &title, const TQString &icon)
{
const int id = m_tabBar->tabs()->count(); // the next available id
const TQString name(widget->name());
TQWidget *tab;
widget->reparent(m_sidebarBox, TQPoint());
widget->hide();
m_tabBar->appendTab(SmallIcon(icon), id, title);
tab = m_tabBar->tab(id);
tab->setFocusPolicy(TQWidget::NoFocus);
// We use a SignalMapper to show/hide the corresponding browser when tabs are clicked
connect(tab, TQ_SIGNAL(clicked()), m_mapper, TQ_SLOT(map()));
m_mapper->setMapping(tab, id);
m_sidebars.push_back(widget);
}
void Sidebar::showHideSidebar(int index)
{
const int prevIndex = m_currentIndex;
if (m_currentIndex != -1) {
// First we need to hide the currentBrowser
m_currentIndex = -1;
m_sidebars[prevIndex]->hide();
m_tabBar->setTab(prevIndex, false);
}
if (index == prevIndex) {
// Close the sidebar
m_sidebarBox->hide();
m_divider->hide();
adjustWidgetSizes();
} else if ((uint) index < m_sidebars.count()) {
// Open up target
TQWidget* const target = m_sidebars[index];
m_currentIndex = index;
m_divider->show();
target->show();
target->setFocus();
m_sidebarBox->show();
m_tabBar->setTab(index, true);
if (prevIndex == -1) {
if (m_position == Left) {
m_pos = m_sidebarBox->width() + m_tabBar->width();
} else {
m_pos = currentSidebar()->height() + m_tabBar->height();
}
adjustWidgetSizes();
}
}
}
TQWidget *Sidebar::sidebar(const TQString &name) const
{
for (SidebarList::ConstIterator it = m_sidebars.begin(), end = m_sidebars.end(); it != end; ++it) {
if (name == (*it)->name())
return *it;
}
return 0;
}
int Sidebar::indexForName(const TQString &name) const
{
for (uint x = 0; x < m_sidebars.count(); ++x) {
if (name == m_sidebars[x]->name())
return x;
}
return -1;
}
}
#include "sidebar.moc"