add a context menu to the log output to allow saving and clearing the log

refactor some code for context menu stuff.

svn path=/trunk/extragear/sysadmin/partitionmanager/; revision=1100535
This commit is contained in:
Volker Lanz 2010-03-07 19:02:02 +00:00
parent 8d71ec34b4
commit 4d6b168474
15 changed files with 253 additions and 91 deletions

4
TODO
View File

@ -21,12 +21,8 @@ Random plans and ideas for 1.1 and beyond:
* let the user specify extern command locations and options in the settings
* make the global log a tree view and add a timestamp column that is hidden by default
* let the user specify in the options which log levels to show in the global log
* add a save option to the global log
* write a setup-kcm in the style of k3b's so that the user can set the r/w
permissions of the disks there; also use kauth to update the partition table
in the kernel. that should cover all cases where we actually need root

View File

@ -13,6 +13,15 @@
<entry name="treePartitionColumnVisible" type="IntList">
<default>1,1,1,1,0,1,1,0,0,0,0,0</default>
</entry>
<entry name="treeLogColumnWidths" type="IntList">
<default>32,192,800</default>
</entry>
<entry name="treeLogColumnPositions" type="IntList">
<default>0,1,2</default>
</entry>
<entry name="treeLogColumnVisible" type="IntList">
<default>1,1,1</default>
</entry>
<entry name="firstRun" type="Bool">
<default>true</default>
</entry>

View File

@ -54,20 +54,6 @@ void ListOperations::updateOperations(const OperationStack::Operations& ops)
void ListOperations::on_m_ListOperations_customContextMenuRequested(const QPoint& pos)
{
if (actionCollection() != NULL)
{
KMenu opsMenu;
if (actionCollection()->action("undoOperation") != NULL)
opsMenu.addAction(actionCollection()->action("undoOperation"));
if (actionCollection()->action("clearAllOperations") != NULL)
opsMenu.addAction(actionCollection()->action("clearAllOperations"));
if (actionCollection()->action("applyAllOperations") != NULL)
opsMenu.addAction(actionCollection()->action("applyAllOperations"));
opsMenu.exec(listOperations().viewport()->mapToGlobal(pos));
}
emit contextMenuRequested(listOperations().viewport()->mapToGlobal(pos));
}

View File

@ -45,6 +45,9 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT ListOperations : public QWidget, public
public:
ListOperations(QWidget* parent);
signals:
void contextMenuRequested(const QPoint&);
public:
void setActionCollection(KActionCollection* coll) { m_ActionCollection = coll; }

View File

@ -84,6 +84,8 @@ MainWindow::MainWindow(QWidget* parent, KActionCollection* coll) :
m_StatusText(new QLabel(this)),
m_InfoPane(new InfoPane(this))
{
Config::instance("partitionmanagerrc");
setupObjectNames();
setupUi(this);
init();
@ -100,7 +102,7 @@ void MainWindow::setupObjectNames()
void MainWindow::init()
{
treeLog().init(actionCollection(), &pmWidget());
treeLog().init();
connect(GlobalLog::instance(), SIGNAL(newMessage(Log::Level, const QString&)), &treeLog(), SLOT(onNewLogMessage(Log::Level, const QString&)));
@ -110,7 +112,7 @@ void MainWindow::init()
listDevices().setActionCollection(actionCollection());
listOperations().setActionCollection(actionCollection());
pmWidget().init(&operationStack(), "partitionmanagerrc");
pmWidget().init(&operationStack());
if (isKPart())
{
@ -346,6 +348,19 @@ void MainWindow::setupActions()
// Settings Actions
KStandardAction::showMenubar(this, SLOT(onShowMenuBar()), actionCollection());
KStandardAction::preferences(this, SLOT(onConfigureOptions()), actionCollection());
// Log Actions
KAction* clearLog = actionCollection()->addAction("clearLog", &treeLog(), SLOT(onClearLog()));
clearLog->setText(i18nc("@action:inmenu", "Clear Log"));
clearLog->setToolTip(i18nc("@info:tooltip", "Clear the log output"));
clearLog->setStatusTip(i18nc("@info:status", "Clear the log output panel."));
clearLog->setIcon(BarIcon("edit-clear-list"));
KAction* saveLog = actionCollection()->addAction("saveLog", &treeLog(), SLOT(onSaveLog()));
saveLog->setText(i18nc("@action:inmenu", "Save Log"));
saveLog->setToolTip(i18nc("@info:tooltip", "Save the log output"));
saveLog->setStatusTip(i18nc("@info:status", "Save the log output to a file."));
saveLog->setIcon(BarIcon("document-save"));
}
void MainWindow::setupConnections()
@ -465,6 +480,22 @@ void MainWindow::updateWindowTitle()
setWindowTitle(title);
}
void MainWindow::on_m_ListOperations_contextMenuRequested(const QPoint& pos)
{
KMenu* menu = static_cast<KMenu*>(guiFactory()->container("edit", this));
if (menu)
menu->exec(pos);
}
void MainWindow::on_m_TreeLog_contextMenuRequested(const QPoint& pos)
{
KMenu* menu = static_cast<KMenu*>(guiFactory()->container("log", this));
if (menu)
menu->exec(pos);
}
void MainWindow::on_m_ListDevices_contextMenuRequested(const QPoint& pos)
{
KMenu* menu = static_cast<KMenu*>(guiFactory()->container("device", this));

View File

@ -142,6 +142,9 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT MainWindow : public KXmlGuiWindow, publi
void on_m_ListDevices_contextMenuRequested(const QPoint& pos);
void on_m_TreeLog_contextMenuRequested(const QPoint& pos);
void on_m_ListOperations_contextMenuRequested(const QPoint& pos);
void onShowMenuBar();
void scanDevices();

View File

@ -77,5 +77,9 @@
<StatusBar/>
<Menu name="log">
<Action name="clearLog"/>
<Action name="saveLog"/>
</Menu>
</gui>

View File

@ -95,12 +95,11 @@ PartitionManagerWidget::~PartitionManagerWidget()
saveConfig();
}
void PartitionManagerWidget::init(OperationStack* ostack, const QString& config_name)
void PartitionManagerWidget::init(OperationStack* ostack)
{
Config::instance(config_name);
m_OperationStack = ostack;
// TODO: shouldn't this also go to the main window class?
FileSystemFactory::init();
loadConfig();
@ -307,33 +306,7 @@ void PartitionManagerWidget::on_m_TreePartitions_itemDoubleClicked(QTreeWidgetIt
void PartitionManagerWidget::onHeaderContextMenu(const QPoint& p)
{
KMenu headerMenu;
headerMenu.addTitle(i18nc("@title:menu", "Columns"));
QHeaderView* header = treePartitions().header();
for (qint32 i = 0; i < treePartitions().model()->columnCount(); i++)
{
const int idx = header->logicalIndex(i);
const QString text = treePartitions().model()->headerData(idx, Qt::Horizontal).toString();
QAction* action = headerMenu.addAction(text);
action->setCheckable(true);
action->setChecked(!header->isSectionHidden(idx));
action->setData(idx);
action->setEnabled(idx > 0);
}
QAction* action = headerMenu.exec(treePartitions().header()->mapToGlobal(p));
if (action != NULL)
{
const bool hidden = !action->isChecked();
treePartitions().setColumnHidden(action->data().toInt(), hidden);
if (!hidden)
treePartitions().resizeColumnToContents(action->data().toInt());
}
showColumnsContextMenu(p, treePartitions());
}
void PartitionManagerWidget::on_m_PartTableWidget_itemSelectionChanged(PartWidget* item)

View File

@ -80,7 +80,7 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget,
void onPropertiesPartition();
public:
void init(OperationStack* ostack, const QString& config_name);
void init(OperationStack* ostack);
void clear();

View File

@ -22,24 +22,131 @@
#include "gui/partitionmanagerwidget.h"
#include "util/globallog.h"
#include "util/helpers.h"
#include <kactioncollection.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kfiledialog.h>
#include <kmessagebox.h>
#include <kstandardguiitem.h>
#include <QFile>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QDateTime>
#include <QTextStream>
#include <config.h>
/** Creates a new TreeLog instance.
@param parent the parent widget
*/
TreeLog::TreeLog(QWidget* parent) :
QWidget(parent),
Ui::TreeLogBase(),
m_ActionCollection(NULL),
m_PartitionManagerWidget(NULL)
Ui::TreeLogBase()
{
setupUi(this);
treeLog().header()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(treeLog().header(), SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onHeaderContextMenu(const QPoint&)));
}
TreeLog::~TreeLog()
{
saveConfig();
}
void TreeLog::init()
{
loadConfig();
}
void TreeLog::loadConfig()
{
QList<int> colWidths = Config::treeLogColumnWidths();
QList<int> colPositions = Config::treeLogColumnPositions();
QList<int> colVisible = Config::treeLogColumnVisible();
QHeaderView* header = treeLog().header();
for (int i = 0; i < treeLog().columnCount(); i++)
{
if (colPositions[0] != -1 && colPositions.size() > i)
header->moveSection(header->visualIndex(i), colPositions[i]);
if (colVisible[0] != -1 && colVisible.size() > i)
treeLog().setColumnHidden(i, colVisible[i] == 0);
if (colWidths[0] != -1 && colWidths.size() > i)
treeLog().setColumnWidth(i, colWidths[i]);
}
}
void TreeLog::saveConfig() const
{
kDebug() << "saving config";
QList<int> colWidths;
QList<int> colPositions;
QList<int> colVisible;
for (int i = 0; i < treeLog().columnCount(); i++)
{
colPositions.append(treeLog().header()->visualIndex(i));
colVisible.append(treeLog().isColumnHidden(i) ? 0 : 1);
colWidths.append(treeLog().columnWidth(i));
}
Config::setTreeLogColumnPositions(colPositions);
Config::setTreeLogColumnVisible(colVisible);
Config::setTreeLogColumnWidths(colWidths);
Config::self()->writeConfig();
}
void TreeLog::onHeaderContextMenu(const QPoint& pos)
{
showColumnsContextMenu(pos, treeLog());
}
void TreeLog::onClearLog()
{
while (QTreeWidgetItem* item = treeLog().takeTopLevelItem(0))
delete item;
}
void TreeLog::onSaveLog()
{
const QString fileName = KFileDialog::getSaveFileName(KUrl("kfiledialog://saveLog"));
if (!fileName.isEmpty())
{
QFile file(fileName);
if (QFile::exists(fileName) && KMessageBox::warningContinueCancel(this, i18nc("@info", "Do you want to overwrite the existing file <filename>%1</filename>?", fileName), i18nc("@title:window", "Overwrite Existing File?"), KGuiItem(i18nc("@action:button", "&Overwrite File")), KStandardGuiItem::cancel()) != KMessageBox::Continue)
return;
if (!file.open(QFile::WriteOnly | QFile::Truncate))
{
KMessageBox::error(this, i18nc("@info", "Could not create output file <filename>%1</filename>.", fileName), i18nc("@title:window", "Error Saving Log File"));
return;
}
QTextStream stream(&file);
for (qint32 idx = 0; idx < treeLog().topLevelItemCount(); idx++)
{
QTreeWidgetItem* item = treeLog().topLevelItem(idx);
stream << item->text(1) << ": " << item->text(2) << "\n";
}
}
}
void TreeLog::on_m_TreeLog_customContextMenuRequested(const QPoint& pos)
{
emit contextMenuRequested(treeLog().viewport()->mapToGlobal(pos));
}
void TreeLog::onNewLogMessage(Log::Level logLevel, const QString& s)
@ -57,13 +164,9 @@ void TreeLog::onNewLogMessage(Log::Level logLevel, const QString& s)
QTreeWidgetItem* item = new QTreeWidgetItem();
item->setIcon(0, SmallIcon(icons[logLevel]));
item->setText(0, QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
item->setText(1, s);
item->setText(1, QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
item->setText(2, s);
treeLog().addTopLevelItem(item);
for (int i = 0; i < treeLog().model()->columnCount(); i++)
treeLog().resizeColumnToContents(i);
treeLog().scrollToBottom();
}

View File

@ -31,8 +31,6 @@
#include <kdebug.h>
class PartitionManagerWidget;
class KActionCollection;
class QTreeWidget;
/** @brief A tree for formatted log output.
@ -45,26 +43,29 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT TreeLog: public QWidget, public Ui::Tree
public:
TreeLog(QWidget* parent);
~TreeLog();
signals:
void contextMenuRequested(const QPoint&);
public:
void init(KActionCollection* coll, PartitionManagerWidget* pm_widget) { m_ActionCollection = coll; m_PartitionManagerWidget = pm_widget; }
void init();
public slots:
protected slots:
void onNewLogMessage(Log::Level logLevel, const QString& s);
void onHeaderContextMenu(const QPoint& pos);
void onClearLog();
void onSaveLog();
void on_m_TreeLog_customContextMenuRequested(const QPoint& pos);
protected:
QTreeWidget& treeLog() { Q_ASSERT(m_TreeLog); return *m_TreeLog; }
const QTreeWidget& treeLog() const { Q_ASSERT(m_TreeLog); return *m_TreeLog; }
PartitionManagerWidget& pmWidget() { Q_ASSERT(m_PartitionManagerWidget); return *m_PartitionManagerWidget; }
const PartitionManagerWidget& pmWidget() const { Q_ASSERT(m_PartitionManagerWidget); return *m_PartitionManagerWidget; }
KActionCollection* actionCollection() { return m_ActionCollection; }
protected slots:
void loadConfig();
void saveConfig() const;
private:
KActionCollection* m_ActionCollection;
PartitionManagerWidget* m_PartitionManagerWidget;
};
#endif

View File

@ -1,7 +1,8 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TreeLogBase</class>
<widget class="QWidget" name="TreeLogBase" >
<property name="geometry" >
<widget class="QWidget" name="TreeLogBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
@ -9,43 +10,57 @@
<height>209</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout" >
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="m_TreeLog" >
<property name="autoScroll" >
<widget class="QTreeWidget" name="m_TreeLog">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="autoScroll">
<bool>false</bool>
</property>
<property name="selectionMode" >
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="textElideMode" >
<property name="textElideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="indentation" >
<property name="indentation">
<number>0</number>
</property>
<property name="rootIsDecorated" >
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="itemsExpandable" >
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="wordWrap" >
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="headerHidden" >
<bool>true</bool>
</property>
<property name="expandsOnDoubleClick" >
<property name="headerHidden">
<bool>false</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<attribute name="headerVisible">
<bool>true</bool>
</attribute>
<attribute name="headerVisible">
<bool>true</bool>
</attribute>
<column>
<property name="text" >
<property name="text">
<string>Sev.</string>
</property>
</column>
<column>
<property name="text">
<string>Time</string>
</property>
</column>
<column>
<property name="text" >
<property name="text">
<string>Message</string>
</property>
</column>

View File

@ -49,7 +49,6 @@ int main(int argc, char* argv[])
return 0;
}
MainWindow* mainWindow = new MainWindow();
mainWindow->show();

View File

@ -30,6 +30,7 @@
#include <kstandarddirs.h>
#include <kcmdlineargs.h>
#include <kdebug.h>
#include <kmenu.h>
#include <QProcess>
#include <QFileInfo>
@ -38,6 +39,8 @@
#include <QIcon>
#include <QPixmap>
#include <QRect>
#include <QTreeWidget>
#include <QHeaderView>
#include <config.h>
@ -144,3 +147,35 @@ QIcon createFileSystemColor(FileSystem::Type type, quint32 size)
return QIcon(pixmap);
}
void showColumnsContextMenu(const QPoint& p, QTreeWidget& tree)
{
KMenu headerMenu;
headerMenu.addTitle(i18nc("@title:menu", "Columns"));
QHeaderView* header = tree.header();
for (qint32 i = 0; i < tree.model()->columnCount(); i++)
{
const int idx = header->logicalIndex(i);
const QString text = tree.model()->headerData(idx, Qt::Horizontal).toString();
QAction* action = headerMenu.addAction(text);
action->setCheckable(true);
action->setChecked(!header->isSectionHidden(idx));
action->setData(idx);
action->setEnabled(true);
}
QAction* action = headerMenu.exec(tree.header()->mapToGlobal(p));
if (action != NULL)
{
const bool hidden = !action->isChecked();
tree.setColumnHidden(action->data().toInt(), hidden);
if (!hidden)
tree.resizeColumnToContents(action->data().toInt());
}
}

View File

@ -28,6 +28,8 @@
class KAboutData;
class QString;
class QIcon;
class QPoint;
class QTreeWidget;
LIBPARTITIONMANAGERPRIVATE_EXPORT void registerMetaTypes();
LIBPARTITIONMANAGERPRIVATE_EXPORT void unblockSigChild();
@ -39,4 +41,6 @@ LIBPARTITIONMANAGERPRIVATE_EXPORT bool caseInsensitiveLessThan(const QString& s1
LIBPARTITIONMANAGERPRIVATE_EXPORT QIcon createFileSystemColor(FileSystem::Type type, quint32 size);
LIBPARTITIONMANAGERPRIVATE_EXPORT void showColumnsContextMenu(const QPoint& p, QTreeWidget& tree);
#endif