4-4 实现Edit菜单(Implement the Edit menu)

  4-4        实现Edit菜单(Implement the Edit menu)
现在我们开始实现菜单Edit相应的槽函数。
void Spreadsheet::cut()
{
    copy();
    del();
}
槽函数cut()相应Edit|Cut菜单,这里调用了两个函数,因为剪切的操作和拷贝然后删除是等价的
void  Spreadsheet::copy()
{
    QTableWidgetSelectionRange range 
=  selectedRange();
    QString str;
    
for  ( int  i  =   0 ; i  <  range.rowCount();  ++ i) {
        
if  (i  >   0 )
            str 
+=   " " ;
        
for  ( int  j  =   0 ; j  <  range.columnCount();  ++ j) {
            
if  (j  >   0 )
                str 
+=   " " ;
            str 
+=  formula(range.topRow()  +  i, range.leftColumn()  +  j);
        }
    }
    QApplication::clipboard()
-> setText(str);
}
QTableWidgetSelectionRange Spreadsheet::selectedRange() 
const
{
    QList
< QTableWidgetSelectionRange >  ranges  =  selectedRanges();
    
if  (ranges.isEmpty())
        
return  QTableWidgetSelectionRange();
    
return  ranges.first();
}
 函数copy()相应Edit|Copy菜单。首先得到当前的选择项(如果没有明确选择,返回当前的网格),然后把选择项的公式按顺序记录下来。行之间用换行符隔开,同一行中每一列之间用TAB隔开。

 

  QApplication::clipboard()可以得到系统的剪贴板。调用QClipboard::setText()把文本放到剪贴板上,这样应用程序中和其他需要文本的Qt程序就可以使用这些文本。用换行符和tab的形式把行列分开也被许多应用程序支持。

QTableWidget::selectedRanges()返回所有的选择范围列表。在Spreadsheet构造函数中我们设置了选择模式为QAbstractItemView::contiguousSelection,因此选择范围只能有一个。为了程序使用方便,定义了selectedRange()函数返回当前的选择范围。
如果有选择范围,则返回第一个且也是唯一的一个选择范围。如果没有明确选择范围,则当前的网格为一个选择(由于ContiguousSelection选择模式)。但是为了程序中可能出现的bug,也处理了选择为空的情况。
 
void  Spreadsheet::paste()
{
    QTableWidgetSelectionRange range 
=  selectedRange();
    QString str 
=  QApplication::clipboard() -> text();
    QStringList rows 
=  str.split( ' ' );
    
int  numRows  =  rows.count();
    
int  numColumns  =  rows.first().count( ' ' +   1 ;
    
if  (range.rowCount()  *  range.columnCount()  !=   1
            
&&  (range.rowCount()  !=  numRows
                
||  range.columnCount()  !=  numColumns)) {
        QMessageBox::information(
this , tr( " Spreadsheet " ),
                tr(
" The information cannot be pasted because the copy  "
                   
" and paste areas aren't the same size. " ));
        
return ;
    }
    
for  ( int  i  =   0 ; i  <  numRows;  ++ i) {
        QStringList columns 
=  rows[i].split( ' ' );
        
for  ( int  j  =   0 ; j  <  numColumns;  ++ j) {
            
int  row  =  range.topRow()  +  i;
            
int  column  =  range.leftColumn()  +  j;
            
if  (row  <  RowCount  &&  column  <  ColumnCount)
                setFormula(row, column, columns[j]);
        }
    }
    somethingChanged();
}
菜单Edit|Paste的槽函数为paste()。我们首先得到剪贴板里的文本,然后调用QString::split()按行把文本分成QStringList。每一行为一个字符串。
接着我们确定拷贝区域的范围。行数为QStringList里QString的个数。列数为第一行中tab的个数加一。如果只有一个网格被选中,我们使用左上角的那个粘贴区域,否则使用当前选择范围为粘贴区域。
粘贴文本时,再一次调用QString::split()把一行文本分裂为每一列文本的组合。
 
4-4 实现Edit菜单(Implement the Edit menu)_第1张图片
 
 
void Spreadsheet::del()
{
    foreach (QTableWidgetItem *item, selectedItems())
        delete item;
}
函数del()相应菜单Edit|Delete。它通过删除表格里选定的Cell对象清除网格。QTableWidget发现QTableWidgetItem被删除后会自动重新绘制所有可见区域。删除网格后,如果调用cell(),将会返回一个空指针。
void Spreadsheet::selectCurrentRow()
{
    selectRow(currentRow());
}
void Spreadsheet::selectCurrentColumn()
{
    selectColumn(currentColumn());
}
以上两个函数分别相应菜单Edit|Select|Row和Edit|Select|Column。通过调用QTableWidget::selectRow()和QTableWidget::selectColumn()。Edit|Select|All菜单操作由QTableWidget的父QTableItemView::selectAll()实现的。
 
void Spreadsheet::findNext(const QString &str, Qt::CaseSensitivity cs)
{
    int row = currentRow();
    int column = currentColumn() + 1;
    while (row < RowCount) {
        while (column < ColumnCount) {
            if (text(row, column).contains(str, cs)) {
                clearSelection();
                setCurrentCell(row, column);
                activateWindow();
                return;
            }
            ++column;
        }
        column = 0;
        ++row;
    }
    QApplication::beep();
}
函数findNext()从当前网格开始向右查找,查找完当前行后向下一行在继续查找,直到发现匹配的文本为止。如果发现了一个匹配,清除当前选择,把匹配的网格做为当前网格,并把相应的窗口激活。如果没有发现则程序beep,说明查找完成但没有成功找到匹配的网格。
void Spreadsheet::findPrevious(const QString &str,
                               Qt::CaseSensitivity cs)
{
    int row = currentRow();
    int column = currentColumn() - 1;
    while (row >= 0) {
        while (column >= 0) {
            if (text(row, column).contains(str, cs)) {
                clearSelection();
                setCurrentCell(row, column);
                activateWindow();
                return;
            }
            --column;
        }
        column = ColumnCount - 1;
        --row;
    }
    QApplication::beep();
}
函数findPrevious()和findNext()很相似,只是搜索顺序是向前向上的,在A1停止。

你可能感兴趣的:(delete,qt,menu,spreadsheet,网格)