|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * split-register-util.c -- split register utilities * 00003 * * 00004 * This program is free software; you can redistribute it and/or * 00005 * modify it under the terms of the GNU General Public License as * 00006 * published by the Free Software Foundation; either version 2 of * 00007 * the License, or (at your option) any later version. * 00008 * * 00009 * This program is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU General Public License for more details. * 00013 * * 00014 * You should have received a copy of the GNU General Public License* 00015 * along with this program; if not, contact: * 00016 * * 00017 * Free Software Foundation Voice: +1-617-542-5942 * 00018 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00019 * Boston, MA 02110-1301, USA gnu@gnu.org * 00020 * * 00021 \********************************************************************/ 00022 00023 #include "config.h" 00024 00025 #include <glib.h> 00026 00027 #include "pricecell.h" 00028 #include "split-register-p.h" 00029 00030 00031 static QofLogModule log_module = GNC_MOD_LEDGER; 00032 00033 00034 /* The routines below create, access, and destroy the SRInfo structure 00035 * used by SplitLedger routines to store data for a particular register. 00036 * This is the only code that should access the user_data member of a 00037 * SplitRegister directly. If additional user data is needed, just add 00038 * it to the SRInfo structure above. */ 00039 static void 00040 gnc_split_register_init_info (SplitRegister *reg) 00041 { 00042 SRInfo *info; 00043 00044 if (reg == NULL) 00045 return; 00046 00047 info = g_new0 (SRInfo, 1); 00048 00049 info->blank_split_guid = *guid_null (); 00050 info->pending_trans_guid = *guid_null (); 00051 info->default_account = *guid_null (); 00052 info->template_account = *guid_null (); 00053 00054 info->last_date_entered = gnc_timet_get_today_start (); 00055 00056 info->first_pass = TRUE; 00057 info->full_refresh = TRUE; 00058 info->separator_changed = TRUE; 00059 00060 reg->sr_info = info; 00061 } 00062 00063 SRInfo * 00064 gnc_split_register_get_info (SplitRegister *reg) 00065 { 00066 if (!reg) 00067 return NULL; 00068 00069 if (reg->sr_info == NULL) 00070 gnc_split_register_init_info (reg); 00071 00072 return reg->sr_info; 00073 } 00074 00075 GtkWidget * 00076 gnc_split_register_get_parent (SplitRegister *reg) 00077 { 00078 SRInfo *info = gnc_split_register_get_info (reg); 00079 00080 if (reg == NULL) 00081 return NULL; 00082 00083 if (info->get_parent == NULL) 00084 return NULL; 00085 00086 return info->get_parent (info->user_data); 00087 } 00088 00089 Split * 00090 gnc_split_register_get_split (SplitRegister *reg, 00091 VirtualCellLocation vcell_loc) 00092 { 00093 GncGUID *guid; 00094 00095 if (reg == NULL) 00096 return NULL; 00097 00098 guid = gnc_table_get_vcell_data (reg->table, vcell_loc); 00099 if (guid == NULL) 00100 return NULL; 00101 00102 return xaccSplitLookup (guid, gnc_get_current_book ()); 00103 } 00104 00105 Account * 00106 gnc_split_register_get_default_account (SplitRegister *reg) 00107 { 00108 SRInfo *info = gnc_split_register_get_info (reg); 00109 00110 return xaccAccountLookup (&info->default_account, 00111 gnc_get_current_book ()); 00112 } 00113 00114 void 00115 gnc_split_register_set_template_account (SplitRegister *reg, 00116 Account *template_account) 00117 { 00118 SRInfo *info = gnc_split_register_get_info (reg); 00119 00120 g_return_if_fail (reg != NULL); 00121 00122 info->template_account = *xaccAccountGetGUID (template_account); 00123 } 00124 00125 Transaction * 00126 gnc_split_register_get_trans (SplitRegister *reg, 00127 VirtualCellLocation vcell_loc) 00128 { 00129 Split *split; 00130 00131 if (!reg || !reg->table) 00132 return NULL; 00133 00134 split = gnc_split_register_get_split (reg, vcell_loc); 00135 00136 if (split != NULL) 00137 return xaccSplitGetParent(split); 00138 00139 /* Split is blank. Assume it is the blank split of a multi-line 00140 * transaction. Go back one row to find a split in the transaction. */ 00141 vcell_loc.virt_row--; 00142 00143 split = gnc_split_register_get_split (reg, vcell_loc); 00144 00145 /* This split could be NULL during register initialization. */ 00146 if (split == NULL) 00147 return NULL; 00148 00149 return xaccSplitGetParent(split); 00150 } 00151 00152 Split * 00153 gnc_split_register_get_trans_split (SplitRegister *reg, 00154 VirtualCellLocation vcell_loc, 00155 VirtualCellLocation *trans_split_loc) 00156 { 00157 CursorClass cursor_class; 00158 00159 if (reg == NULL) 00160 return NULL; 00161 00162 while (TRUE) 00163 { 00164 if ((0 > vcell_loc.virt_row) || (0 > vcell_loc.virt_col)) 00165 { 00166 PERR ("bad row \n"); 00167 return NULL; 00168 } 00169 00170 cursor_class = gnc_split_register_get_cursor_class (reg, vcell_loc); 00171 00172 if (cursor_class == CURSOR_CLASS_TRANS) 00173 { 00174 if (trans_split_loc) 00175 *trans_split_loc = vcell_loc; 00176 00177 return gnc_split_register_get_split (reg, vcell_loc); 00178 } 00179 00180 vcell_loc.virt_row--; 00181 } 00182 } 00183 00184 Split * 00185 gnc_split_register_get_current_trans_split( 00186 SplitRegister *reg, VirtualCellLocation *trans_split_loc) 00187 { 00188 VirtualCellLocation vcell_loc; 00189 00190 if (reg == NULL) 00191 return NULL; 00192 00193 vcell_loc = reg->table->current_cursor_loc.vcell_loc; 00194 00195 return gnc_split_register_get_trans_split (reg, vcell_loc, trans_split_loc); 00196 } 00197 00198 gboolean 00199 gnc_split_register_find_split (SplitRegister *reg, 00200 Transaction *trans, Split *trans_split, 00201 Split *split, CursorClass find_class, 00202 VirtualCellLocation *vcell_loc) 00203 { 00204 Table *table = reg->table; 00205 gboolean found_trans = FALSE; 00206 gboolean found_trans_split = FALSE; 00207 gboolean found_something = FALSE; 00208 CursorClass cursor_class; 00209 int v_row, v_col; 00210 Transaction *t; 00211 Split *s; 00212 00213 for (v_row = 1; v_row < table->num_virt_rows; v_row++) 00214 for (v_col = 0; v_col < table->num_virt_cols; v_col++) 00215 { 00216 VirtualCellLocation vc_loc = { v_row, v_col }; 00217 00218 s = gnc_split_register_get_split (reg, vc_loc); 00219 t = xaccSplitGetParent(s); 00220 00221 cursor_class = gnc_split_register_get_cursor_class (reg, vc_loc); 00222 00223 if (t == trans) 00224 { 00225 /* A register entry for the correct transaction. */ 00226 found_trans = TRUE; 00227 00228 if (cursor_class == CURSOR_CLASS_TRANS) 00229 { 00230 /* This row is the transaction split for this transaction. */ 00231 if (s == trans_split) 00232 /* It's the copy of the transaction that we want. */ 00233 found_trans_split = TRUE; 00234 else 00235 found_trans_split = FALSE; 00236 00237 if (find_class == CURSOR_CLASS_TRANS && 00238 (s == split || reg->style == REG_STYLE_JOURNAL)) 00239 { 00240 /* We're looking for a transaction split and this is the split we're looking for 00241 or there is only one entry for this transaction in this register (since it's 00242 a journal style register) so we must return the only transaction split there is. */ 00243 if (vcell_loc != NULL) 00244 *vcell_loc = vc_loc; 00245 return TRUE; 00246 } 00247 } 00248 } 00249 else 00250 { 00251 /* Not the correct transaction. We shouldn't get here if these are true, but just 00252 to be safe reset them. */ 00253 found_trans = FALSE; 00254 found_trans_split = FALSE; 00255 } 00256 00257 if (found_trans && (s == split) && s) 00258 { 00259 /* We're on the right transaction, but perhaps not the copy of it we want, and 00260 this is the correct split, return it if we don't find anything better. */ 00261 if (vcell_loc != NULL) 00262 *vcell_loc = vc_loc; 00263 00264 found_something = TRUE; 00265 } 00266 00267 if (found_trans_split && (s == split)) 00268 { 00269 /* We're on the right copy of the right transaction, and this is the split we 00270 want, return it (it should be the right class since if we wanted a transaction 00271 split we would have returned it above. */ 00272 if (vcell_loc != NULL) 00273 *vcell_loc = vc_loc; 00274 00275 if (cursor_class == find_class) 00276 return TRUE; 00277 } 00278 } 00279 00280 return found_something; 00281 } 00282 00283 void 00284 gnc_split_register_show_trans (SplitRegister *reg, 00285 VirtualCellLocation start_loc) 00286 { 00287 VirtualCellLocation end_loc; 00288 int v_row; 00289 00290 end_loc = start_loc; 00291 00292 for (v_row = end_loc.virt_row + 1; 00293 v_row < reg->table->num_virt_rows; v_row++) 00294 { 00295 VirtualCellLocation vc_loc = { v_row, 0 }; 00296 CursorClass cursor_class; 00297 00298 cursor_class = gnc_split_register_get_cursor_class (reg, vc_loc); 00299 if (cursor_class == CURSOR_CLASS_TRANS) 00300 break; 00301 00302 if (cursor_class != CURSOR_CLASS_SPLIT) 00303 { 00304 v_row--; 00305 break; 00306 } 00307 } 00308 00309 end_loc.virt_row = MIN (v_row, reg->table->num_virt_rows - 1); 00310 00311 gnc_table_show_range (reg->table, start_loc, end_loc); 00312 } 00313 00314 void 00315 gnc_split_register_set_trans_visible (SplitRegister *reg, 00316 VirtualCellLocation vcell_loc, 00317 gboolean visible, 00318 gboolean only_blank_split) 00319 { 00320 CursorClass cursor_class; 00321 00322 while (TRUE) 00323 { 00324 vcell_loc.virt_row++; 00325 00326 cursor_class = gnc_split_register_get_cursor_class (reg, vcell_loc); 00327 if (cursor_class != CURSOR_CLASS_SPLIT) 00328 return; 00329 00330 if (only_blank_split && gnc_split_register_get_split (reg, vcell_loc)) 00331 continue; 00332 00333 gnc_table_set_virt_cell_visible (reg->table, vcell_loc, visible); 00334 } 00335 } 00336 00337 void 00338 gnc_split_register_set_cell_fractions (SplitRegister *reg, Split *split) 00339 { 00340 Account *account; 00341 Transaction *trans; 00342 gnc_commodity *currency; 00343 PriceCell *cell; 00344 int fraction; 00345 00346 trans = xaccSplitGetParent (split); 00347 currency = xaccTransGetCurrency (trans); 00348 if (!currency) 00349 currency = gnc_default_currency (); 00350 00351 fraction = gnc_commodity_get_fraction (currency); 00352 00353 cell = (PriceCell *) gnc_table_layout_get_cell (reg->table->layout, 00354 DEBT_CELL); 00355 gnc_price_cell_set_fraction (cell, fraction); 00356 00357 cell = (PriceCell *) gnc_table_layout_get_cell (reg->table->layout, 00358 CRED_CELL); 00359 gnc_price_cell_set_fraction (cell, fraction); 00360 00361 account = xaccSplitGetAccount (split); 00362 00363 cell = (PriceCell *) gnc_table_layout_get_cell (reg->table->layout, 00364 SHRS_CELL); 00365 00366 if (account) 00367 gnc_price_cell_set_fraction (cell, xaccAccountGetCommoditySCU (account)); 00368 else 00369 gnc_price_cell_set_fraction (cell, 1000000); 00370 } 00371 00372 CellBlock * 00373 gnc_split_register_get_passive_cursor (SplitRegister *reg) 00374 { 00375 const char *cursor_name = NULL; 00376 00377 switch (reg->style) 00378 { 00379 case REG_STYLE_LEDGER: 00380 case REG_STYLE_AUTO_LEDGER: 00381 cursor_name = reg->use_double_line ? 00382 CURSOR_DOUBLE_LEDGER : CURSOR_SINGLE_LEDGER; 00383 break; 00384 00385 case REG_STYLE_JOURNAL: 00386 cursor_name = reg->use_double_line ? 00387 CURSOR_DOUBLE_JOURNAL : CURSOR_SINGLE_JOURNAL; 00388 break; 00389 } 00390 00391 if (!cursor_name) 00392 { 00393 PWARN ("bad register style"); 00394 return NULL; 00395 } 00396 00397 return gnc_table_layout_get_cursor (reg->table->layout, cursor_name); 00398 } 00399 00400 CellBlock * 00401 gnc_split_register_get_active_cursor (SplitRegister *reg) 00402 { 00403 SRInfo *info = gnc_split_register_get_info (reg); 00404 const char *cursor_name = NULL; 00405 00406 switch (reg->style) 00407 { 00408 case REG_STYLE_LEDGER: 00409 if (!info->trans_expanded) 00410 { 00411 cursor_name = reg->use_double_line ? 00412 CURSOR_DOUBLE_LEDGER : CURSOR_SINGLE_LEDGER; 00413 break; 00414 } 00415 00416 /* fall through */ 00417 case REG_STYLE_AUTO_LEDGER: 00418 case REG_STYLE_JOURNAL: 00419 cursor_name = reg->use_double_line ? 00420 CURSOR_DOUBLE_JOURNAL : CURSOR_SINGLE_JOURNAL; 00421 break; 00422 } 00423 00424 if (!cursor_name) 00425 { 00426 PWARN ("bad register style"); 00427 return NULL; 00428 } 00429 00430 return gnc_table_layout_get_cursor (reg->table->layout, cursor_name); 00431 } 00432 00433 void 00434 gnc_split_register_set_last_num (SplitRegister *reg, const char *num) 00435 { 00436 Account *account; 00437 00438 account = gnc_split_register_get_default_account (reg); 00439 if (!account) 00440 return; 00441 00442 xaccAccountSetLastNum (account, num); 00443 } 00444 00445 static CursorClass 00446 gnc_split_register_cursor_class (SplitRegister *reg, 00447 CellBlock *cursor) 00448 { 00449 if (cursor == NULL) 00450 return CURSOR_CLASS_NONE; 00451 00452 return gnc_split_register_cursor_name_to_class (cursor->cursor_name); 00453 } 00454 00455 CursorClass 00456 gnc_split_register_get_cursor_class (SplitRegister *reg, 00457 VirtualCellLocation vcell_loc) 00458 { 00459 VirtualCell *vcell; 00460 Table *table; 00461 00462 if (reg == NULL) 00463 return CURSOR_CLASS_NONE; 00464 00465 table = reg->table; 00466 if (table == NULL) 00467 return CURSOR_CLASS_NONE; 00468 00469 vcell = gnc_table_get_virtual_cell (table, vcell_loc); 00470 if (vcell == NULL) 00471 return CURSOR_CLASS_NONE; 00472 00473 return gnc_split_register_cursor_class (reg, vcell->cellblock); 00474 } 00475 00476 CursorClass 00477 gnc_split_register_get_current_cursor_class (SplitRegister *reg) 00478 { 00479 Table *table; 00480 00481 if (reg == NULL) 00482 return CURSOR_CLASS_NONE; 00483 00484 table = reg->table; 00485 if (table == NULL) 00486 return CURSOR_CLASS_NONE; 00487 00488 return gnc_split_register_cursor_class (reg, table->current_cursor); 00489 } 00490 00491 CursorClass 00492 gnc_split_register_cursor_name_to_class (const char *cursor_name) 00493 { 00494 if (cursor_name == NULL) 00495 return CURSOR_CLASS_NONE; 00496 00497 if (strcmp (cursor_name, CURSOR_SINGLE_LEDGER) == 0 || 00498 strcmp (cursor_name, CURSOR_DOUBLE_LEDGER) == 0 || 00499 strcmp (cursor_name, CURSOR_SINGLE_JOURNAL) == 0 || 00500 strcmp (cursor_name, CURSOR_DOUBLE_JOURNAL) == 0) 00501 return CURSOR_CLASS_TRANS; 00502 00503 if (strcmp (cursor_name, CURSOR_SPLIT) == 0) 00504 return CURSOR_CLASS_SPLIT; 00505 00506 return CURSOR_CLASS_NONE; 00507 }
1.7.4