Logo Search packages:      
Sourcecode: webissues version File versions  Download package

projectsview.cpp

/**************************************************************************
* This file is part of the WebIssues program
* Copyright (C) 2006 Michał Męciński
* Copyright (C) 2007 WebIssues Team
*
* 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 "projectsview.h"

#include <QTreeView>
#include <QAction>
#include <QMenu>
#include <QTimer>
#include <QMessageBox>

#include "models/tableitemmodel.h"
#include "models/tablemodels.h"
#include "models/treeviewsettings.h"
#include "models/treeviewhelper.h"
#include "data/rdb/tableiterators.h"
#include "data/datamanager.h"
#include "data/connectioninfo.h"
#include "data/updatebatch.h"
#include "dialogs/projectdialogs.h"
#include "dialogs/finditemdialog.h"
#include "dialogs/userdialogs.h"
#include "xmlui/builder.h"
#include "connectionmanager.h"
#include "configdata.h"
#include "viewmanager.h"
#include "iconloader.h"

using namespace WebIssues;

00039 ProjectsView::ProjectsView( QObject* parent, QWidget* parentWidget ) : View( parent ),
    m_firstUpdateDone( false ),
    m_updateCounter( 0 )
{
    m_systemAdmin = connectionManager->connectionInfo()->access() == AdminAccess;

    QAction* action;

    action = new QAction( IconLoader::icon( "file-reload" ), tr( "&Update Projects" ), this );
    action->setShortcut( QKeySequence::Refresh );
    connect( action, SIGNAL( triggered() ), this, SLOT( updateProjects() ) );
    setAction( "updateProjects", action );

    action = new QAction( IconLoader::icon( "view-users" ), tr( "&User Accounts" ), this );
    connect( action, SIGNAL( triggered() ), this, SLOT( showUsers() ) );
    setAction( "showUsers", action );

    action = new QAction( IconLoader::icon( "view-types" ), tr( "Issue &Types" ), this );
    connect( action, SIGNAL( triggered() ), this, SLOT( showTypes() ) );
    setAction( "showTypes", action );

    action = new QAction( IconLoader::icon( "view-members" ), tr( "Project &Members" ), this );
    connect( action, SIGNAL( triggered() ), this, SLOT( showMembers() ) );
    setAction( "showMembers", action );

    if ( m_systemAdmin ) {
        action = new QAction( IconLoader::icon( "project-new" ), tr( "Add &Project..." ), this );
        connect( action, SIGNAL( triggered() ), this, SLOT( addProject() ) );
        setAction( "addProject", action );
    }

    action = new QAction( IconLoader::icon( "folder-new" ), tr( "Add &Folder..." ), this );
    action->setShortcut( QKeySequence::New );
    connect( action, SIGNAL( triggered() ), this, SLOT( addFolder() ) );
    setAction( "addFolder", action );

    action = new QAction( IconLoader::icon( "edit-rename" ), tr( "&Rename..." ), this );
    action->setShortcut( tr( "F2" ) );
    connect( action, SIGNAL( triggered() ), this, SLOT( editRename() ) );
    setAction( "editRename", action );

    action = new QAction( IconLoader::icon( "edit-delete" ), tr( "&Delete" ), this );
    action->setShortcut( QKeySequence::Delete );
    connect( action, SIGNAL( triggered() ), this, SLOT( editDelete() ) );
    setAction( "editDelete", action );

    action = new QAction( IconLoader::icon( "folder-open" ), tr( "&Open Folder" ), this );
    action->setShortcut( QKeySequence::Open );
    connect( action, SIGNAL( triggered() ), this, SLOT( openFolder() ) );
    setAction( "openFolder", action );

    action = new QAction( IconLoader::icon( "find" ), tr( "&Find Item..." ), this );
    action->setShortcut( QKeySequence::Find );
    connect( action, SIGNAL( triggered() ), this, SLOT( findItem() ) );
    setAction( "findItem", action );

    action = new QAction( IconLoader::icon( "edit-password" ), tr( "Change &Password..." ), this );
    connect( action, SIGNAL( triggered() ), this, SLOT( changePassword() ) );
    setAction( "changePassword", action );

    setTitle( "menuProjects", tr( "&Projects" ) );
    setTitle( "menuEdit", tr( "&Edit" ) );

    loadXmlFile( ":/resources/projectsview.xml" );

    m_list = new QTreeView( parentWidget );
    m_list->setRootIsDecorated( true );
    m_list->setSortingEnabled( true );
    m_list->setContextMenuPolicy( Qt::CustomContextMenu );

    connect( m_list, SIGNAL( customContextMenuRequested( const QPoint& ) ),
        this, SLOT( contextMenu( const QPoint& ) ) );
    connect( m_list, SIGNAL( doubleClicked( const QModelIndex& ) ),
        this, SLOT( doubleClicked( const QModelIndex& ) ) );

    setMainWidget( m_list );
}

00117 ProjectsView::~ProjectsView()
{
    TreeViewSettings settings;
    settings.openProjectsTree();

    settings.saveColumnWidths( TreeViewHelper::readColumnWidths( m_list ) );
    if ( m_firstUpdateDone )
        settings.saveExpandedNodes( TreeViewHelper::readExpandedNodes( m_list ) );
}

00127 void ProjectsView::initialUpdate()
{
    m_model = new TableItemModel( this );
    m_model->setRootTableModel( new ProjectsTableModel( m_model ), dataManager->projects()->index() );
    m_model->addChildTableModel( new FoldersTableModel( m_model ), dataManager->folders()->parentIndex() );

    TreeViewSettings settings;
    settings.openProjectsTree();

    m_model->setColumns( settings.loadColumns() );

    m_list->setModel( m_model );

    m_list->sortByColumn( 0, Qt::AscendingOrder );

    TreeViewHelper::applyColumnWidths( m_list, settings.loadColumnWidths() );

    connect( m_model->rootTableModel(), SIGNAL( tableChanged() ), this, SLOT( projectsTableChanged() ) );

    setCaption( connectionManager->connectionInfo()->serverName() );

    connect( m_list->selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ),
        this, SLOT( updateActions() ) );
    connect( m_model, SIGNAL( layoutChanged() ), this, SLOT( updateActions() ) );

    updateActions();
    updateSummary();

    periodicUpdate( true );

    QTimer* timer = new QTimer( this );
    connect( timer, SIGNAL( timeout() ), this, SLOT( updateTimeout() ) );
    timer->start( 60 * 1000 );

    setAccess( checkDataAccess(), true );
}

Access ProjectsView::checkDataAccess()
{
    m_anyProjectAdmin = m_systemAdmin;

    int userId = connectionManager->connectionInfo()->userId();
    RDB::ForeignConstIterator<MemberRow> it( dataManager->members()->index(), userId );
    while ( it.next() ) {
        const MemberRow* member = it.get();
        if ( member->access() == AdminAccess )
            m_anyProjectAdmin = true;
    }

    return m_anyProjectAdmin ? AdminAccess : NormalAccess;
}

00179 void ProjectsView::updateAccess( Access access )
{
    action( "addFolder" )->setVisible( m_anyProjectAdmin );
    action( "editRename" )->setVisible( m_systemAdmin || m_anyProjectAdmin );
    action( "editDelete" )->setVisible( m_systemAdmin || m_anyProjectAdmin );
}

void ProjectsView::updateTimeout()
{
    m_updateCounter++;

    if ( m_updateCounter >= configData->updateInterval() ) {
        periodicUpdate( false );

        m_updateCounter = 0;
    }
}

void ProjectsView::periodicUpdate( bool initial )
{
    UpdateBatch* batch = new UpdateBatch( initial ? -1 : -10 );
    batch->updateUsers();
    batch->updateTypes();
    batch->updateProjects();

    executeUpdate( batch );
}

void ProjectsView::updateActions()
{
    m_selectedProjectId = 0;
    m_selectedFolderId = 0;
    m_currentProjectId = 0;

    QModelIndex index = selectedIndex();
    if ( index.isValid() ) {
        int level = m_model->data( index, TableItemModel::LevelRole ).toInt();
        int rowId = m_model->data( index, TableItemModel::RowIdRole ).toInt();
        if ( level == 0 ) {
            m_selectedProjectId = rowId;
            m_currentProjectId = rowId;
        } else {
            m_selectedFolderId = rowId;
            const FolderRow* folder = dataManager->folders()->find( rowId );
            if ( folder )
                m_currentProjectId = folder->projectId();
        }
    }

    m_currentProjectAdmin = m_systemAdmin;

    if ( m_currentProjectId != 0 ) {
        int userId = connectionManager->connectionInfo()->userId();
        const MemberRow* member = dataManager->members()->find( userId, m_currentProjectId );
        if ( member && member->access() == AdminAccess )
            m_currentProjectAdmin = true;
    }

    action( "showMembers" )->setEnabled( m_currentProjectId != 0 );
    action( "openFolder" )->setEnabled( m_selectedFolderId != 0 );
    action( "addFolder" )->setEnabled( m_currentProjectId != 0 && m_currentProjectAdmin );
    action( "editRename" )->setEnabled( m_selectedProjectId != 0 && m_systemAdmin || m_selectedFolderId != 0 && m_currentProjectAdmin );
    action( "editDelete" )->setEnabled( m_selectedProjectId != 0 && m_systemAdmin || m_selectedFolderId != 0 && m_currentProjectAdmin );
}

void ProjectsView::updateProjects()
{
    if ( !isUpdating() ) {
        UpdateBatch* batch = new UpdateBatch();
        batch->updateProjects();

        executeUpdate( batch );
    }
}

void ProjectsView::showUsers()
{
    viewManager->openUsersView();
}

void ProjectsView::showTypes()
{
    viewManager->openTypesView();
}

void ProjectsView::showMembers()
{
    if ( m_currentProjectId != 0 )
        viewManager->openMembersView( m_currentProjectId );
}

void ProjectsView::addProject()
{
    if ( m_systemAdmin ) {
        AddProjectDialog dialog( mainWidget() );
        dialog.exec();
    }
}

void ProjectsView::addFolder()
{
    if ( m_currentProjectId != 0 && m_currentProjectAdmin ) {
        AddFolderDialog dialog( m_currentProjectId, mainWidget() );
        dialog.exec();
    }
}

void ProjectsView::editRename()
{
    if ( m_selectedProjectId != 0 && m_systemAdmin ) {
        RenameProjectDialog dialog( m_selectedProjectId, mainWidget() );
        dialog.exec();
    } else if ( m_selectedFolderId != 0 && m_currentProjectAdmin ) {
        RenameFolderDialog dialog( m_selectedFolderId, mainWidget() );
        dialog.exec();
    }
}

void ProjectsView::editDelete()
{
    if ( m_selectedProjectId != 0 && m_systemAdmin ) {
        RDB::ForeignConstIterator<FolderRow> it( dataManager->folders()->parentIndex(), m_selectedProjectId );
        if ( it.next() ) {
            const ProjectRow* project = dataManager->projects()->find( m_selectedProjectId );
            QString name = project ? project->name() : QString();
            QMessageBox::warning( mainWidget(), tr( "Delete Project" ),
                tr( "<qt>Project <b>%1</b> cannot be deleted because it is not empty.</qt>" ).arg( name ) );
            return;
        }
        DeleteProjectDialog dialog( m_selectedProjectId, mainWidget() );
        dialog.exec();
    } else if ( m_selectedFolderId != 0 && m_currentProjectAdmin ) {
        const FolderRow* folder = dataManager->folders()->find( m_selectedFolderId );
        if ( folder && folder->stamp() > 0 ) {
            QString name = folder->name();
            QMessageBox::warning( mainWidget(), tr( "Delete Folder" ),
                tr( "<qt>Folder <b>%1</b> cannot be deleted because it is not empty.</qt>" ).arg( name ) );
            return;
        }
        DeleteFolderDialog dialog( m_selectedFolderId, mainWidget() );
        dialog.exec();
    }
}

void ProjectsView::openFolder()
{
    if ( m_selectedFolderId != 0  )
        viewManager->openFolderView( m_selectedFolderId );
}

void ProjectsView::findItem()
{
    FindItemDialog dialog( mainWidget() );
    if ( dialog.exec() == QDialog::Accepted )
        viewManager->openIssueView( dialog.issueId(), dialog.itemId() );
}

void ProjectsView::changePassword()
{
    SetPasswordDialog dialog( connectionManager->connectionInfo()->userId(), mainWidget() );
    dialog.exec();
}

void ProjectsView::updateSummary()
{
    int userId = connectionManager->connectionInfo()->userId();
    const UserRow* user = dataManager->users()->find( userId );
    QString name = user ? user->name() : QString();

    QPixmap pixmap = m_systemAdmin ? IconLoader::overlayedPixmap( "user", "overlay-admin" ) : IconLoader::pixmap( "user" );

    emit showSummary( pixmap, name );
}

00353 void ProjectsView::updateEvent( UpdateEvent* e )
{
    setAccess( checkDataAccess() );

    if ( e->unit() == UpdateEvent::Users )
        updateSummary();
}

void ProjectsView::projectsTableChanged()
{
    if ( !m_firstUpdateDone ) {
        TreeViewSettings settings;
        settings.openProjectsTree();

        TreeViewHelper::applyExpandedNodes( m_list, settings.loadExpandedNodes() );

        m_firstUpdateDone = true;
    }
}

void ProjectsView::contextMenu( const QPoint& pos )
{
    QModelIndex index = m_list->indexAt( pos );

    QString menuName;
    if ( index.isValid() ) {
        int level = m_model->data( index, TableItemModel::LevelRole ).toInt();
        if ( level == 0 )
            menuName = m_systemAdmin ? "contextProjectAdmin" : "contextProject";
        else
            menuName = "contextFolder";
    } else {
        menuName = "contextNull";
    }

    QMenu* menu = builder()->contextMenu( menuName );
    if ( menu )
        menu->exec( m_list->viewport()->mapToGlobal( pos ) );
}

void ProjectsView::doubleClicked( const QModelIndex& index )
{
    if ( index.isValid() ) {
        int level = m_model->data( index, TableItemModel::LevelRole ).toInt();
        int rowId = m_model->data( index, TableItemModel::RowIdRole ).toInt();

        if ( level == 1 )
            viewManager->openFolderView( rowId );
    }
}

QModelIndex ProjectsView::selectedIndex()
{
    if ( !m_list->selectionModel() )
        return QModelIndex();

    QModelIndexList selection = m_list->selectionModel()->selectedRows();
    if ( selection.isEmpty() )
        return QModelIndex();

    return selection.at( 0 );
}

#include "projectsview.moc"

Generated by  Doxygen 1.6.0   Back to index